|
|
#1 |
|
* Confusion in C
To figure out pointers, I thought of the * in C as having three proper usages:
1 - It may be used for multiplication, like here: Code:
product = factor1 * factor2; Code:
runningProduct *= factor; Code:
char* charPtr; int* intPtr; float* floatPtr; double* doublePtr; void* voidPtr; Code:
typedef struct {
int a;
int b;
} MyStruct;
MyStruct* myStructPtr;
Code:
*intPtr = 3; // Sets the value at the address intPtr points to to 3. int localInt = *intPtr; // localInt now holds the value at the address intPtr point to - which we know to be 3 in this example. When using it the first way, for multiplication, there is a space before and after it, " * ". When using it the second way, to declare a pointer type, I put a space after but not before it, "* ". When using it the third way, to dereference a pointer variable, I put a space before but not after it, " *". Am I correct so far in thinking of the * as being used in three different ways? I believe I am, as I've been writing functional code with all that preceded for the last 2 years now. I've decided that I'd like to try my hand at making a C IDE for iOS, partially because I'm not content with them, and partially because I suspect that in doing so, I'll master the C language. So, having said that, I've run into this funky line in C... This line declares a pointer, named ptr, to an array of characters. Code:
char(* ptr)[]; This couldn't be rewritten as: Code:
char* ptr[]; If I try to write it as: Code:
char(char* ptr)[]; While I'm on this topic... why are brackets places after the identifier of the variable instead of after the type? When I write something like Code:
int* ptr; But if I want an array like this: Code:
int arr[]; I don't care about the array complaint as much as the pointer confusion... which actually confuses me. Edit: Somehow, I completely forgot about the rabbit hole that is C function pointers: http://stackoverflow.com/questions/1...c-declarations Here's an explanation of how to read them aloud: http://c-faq.com/decl/spiral.anderson.html So... now I'm feeling a bit more lost than before... I'm going to go sleep on this now, I guess...
__________________
Battery Status - On the Mac App Store
The only app that'll estimate when your wireless devices will need their batteries changed. Like it on Facebook! Last edited by ArtOfWarfare; Jan 7, 2013 at 08:40 PM. |
|
|
|
0
|
|
|
#2 |
|
You don't declare a pointer as "pointer to array of T", where T is some type. That's because there is no syntactical difference between "pointer to array of T" and "pointer to singular T". Here's why:
Every C pointer is implicitly a pointer to an array.Every pointer can be subscripted, like so: Code:
char * p = somethingThatReturnsPtrToChar; char a = p[0]; char b = p[1]; char wtf = p[-1]; This may all seem strange, but that's because you're thinking of C arrays as different from pointers. The only difference between them lies in their definitions, not their types. Here's another strange truth: Every array name is a constant pointer to the first array element.For example, int bb[ 10 ]; the type of bb by itself is pointer to int. So every place you have an array subscript, think of the array name as being a constant pointer, and voila, pointer subscripting is identical to array subscripting. A pointer variable can have operators that change it (like ++), and can be assigned a new value. A pointer constant cannot. So if you think of the array name bb by itself, with no subscript, you can do all things with bb that you can do with a variable pointer, except those things that modify the pointer itself. You can subscript it, you can add expressions as long as the result is stored in a different pointer, you can even use pointer arithmetic, like so: Code:
int bb[ 10 ]; bb[ 0 ] = 98; bb[ 1 ] = 2; bb[ 2 ] = *bb + *(bb + 1); *(bb + 3) = bb[0] + bb[1]; The unary * operator (pointer dereference) is exactly equivalent to array subscripting with an index value of 0. And dereferencing via pointer arithmetic is identical to subscripting: Code:
int * p = somethingThatReturnsPtrToInt; int a = p[0]; int aa = *p; // exactly equivalent int b = p[1]; int bb = *(p + 1); // exactly equivalent int wtf = p[-1]; int wwtf = *(p - 1); // exactly equivalent You should also study C type declarations and definitions, because how types are defined is different from how operators are used. The book "The C Programming Language" by K&R is the definitive book for pointers and type definitions, in my view, but some people need more examples and more detailed explanations. Finally, I strongly advise against this style: Code:
char* charPtr; Code:
char* cc, dd; Code:
char* cc, * dd; Code:
char* cc, ee[ 10 ]; |
|
|
|
0
|
|
|
#3 |
|
Thank you for the large amount of samples, Chown. The weirder valid code I can find, the better (because ultimately my app needs to accept all of it without complaining, while still pointing out invalid code.)
|
|
|
|
0
|
|
|
#4 |
|
Also keep in mind that an array in C is actually a list of pointers. A pointer is nothing more than a memory address which may contain one or many pointers (as you can ask for a pointer to point to a block of memory, hence an array).
__________________
MBA 13", i5 1.8GHz, 8GM RAM, 128GB SSD These are amazing products that enrich our lives that we see as toys, remember that they are expensive and should be used as tools to reach our dreams~
|
|
|
|
0
|
|
|
#5 |
|
|
0
|
|
|
#6 |
|
Interestingly, an array reference in C is simply a macro. That is, "a[b]" is simply converted to "*(a + b)". The net result of this is that "foo[10]" is an equivalent statement to (the also syntactically valid) "10[foo]". Try it out if you don't believe me.
|
|
|
|
0
|
|
|
#7 |
|
Now that ..., I believe!
Last edited by lloyddean; Jan 8, 2013 at 12:24 AM. |
|
|
|
0
|
|
|
#8 | |
|
Quote:
The highlighted bit is only true for an array of byte-sized entries I presume, or else the statement above is simplified slightly.
__________________
Mac <- Macintosh <- McIntosh apples <- John McIntosh <- McIntosh surname <- "Mac an toshach" <- "Son of the Chief" |
||
|
|
0
|
|
|
#9 | |
|
Quote:
---------- It's actually true in all cases. When you add to a pointer the actual pointer valid increases by the size of the base type. If I have a pointer to a 32 bit number and increment it by 1 (p++) the actual value of p increases by 4. This makes iterating through memory with a pointer a lot easier. |
||
|
|
0
|
|
|
#10 | ||
|
Quote:
I'm not saying it's correct to use every pointer as a pointer to an array. That's the difference between explicit array pointers and implicit ones. If C had explicit array pointers, then array bounds would be part of the pointer type, and it would be impossible to move the pointer outside the array. But C doesn't do that. Instead, it lets you point any pointer anywhere, regardless of whether it's to a scalar value or to any array, and there is no way to express a distinction in the language. Thus, every C pointer is implicitly a pointer to an array. Quote:
|
|||
|
|
0
|
|
|
#11 |
|
There is fertile ground for confusion here. When I declare
Code:
NSString *aString; I suppose it is lamentable that NeXT did not decide to define object references as opaque types in order to reduce confusion.
__________________
Mr. Paul, sir, I thought you should be advised, there seems to be a zombie tribble clinging to your head, for it is scarfing your brain
|
|
|
|
0
|
|
|
#12 |
|
Actually, in C, it is... although, in Objective C, ARC would probably complain if you tried to assign a C array of object pointers (such as NSString objects) to aString. But with ARC disabled, you could assign a C array of retained NSString objects to it. Legal, but stylistically very poor.
|
|
|
|
0
|
|
|
#13 | ||
|
Quote:
An Objective-C object pointer is not implicitly a pointer to an array of objects, because Objective-C does not allow non-pointer objects. There's no way to deference a pointer to an object and get the "naked" object. The Objective-C compiler rejects such attempts (or should). Quote:
FWIW, NeXT didn't invent Objective-C, so they really didn't get much choice about what constitutes an object reference: http://en.wikipedia.org/wiki/Objective-C#History Objective-C was created primarily by Brad Cox and Tom Love in the early 1980s at their company Stepstone.As is often the case with C-derived languages, first attempts are typically pre-processors of some kind, and that limits the extent to which the underlying language syntax can be altered. |
|||
|
|
0
|
|
|
#14 |
|
Your nomenclature seems to be slightly skewed from the norm.
For most developers an array is a variable that is declared. The declared keyword's value is a constant pointer, and that pointer is backed by a region of memory. A pointer is a memory address and a type enforced at compile time. A pointer to an array of integers is a pointer to a pointer (int**). This can not be implicitly cast into an array of integers (int array[]), or into a pointer to a single integer (int* pointer). |
|
|
|
0
|
|
|
#15 |
|
A pointer is simply a location in memory of sufficient size to hold the address of another location in memory.
|
|
|
|
0
|
|
|
#16 | |
|
Quote:
Yes, it may be preferable to use indirection in arrays, but actual C nomenclature does not call those "proper arrays" vs. OIDK, "dirty dangerous arrays". An ordered sequence of elements is an array, be it comprised of pointers, bytes or structs.
__________________
Mr. Paul, sir, I thought you should be advised, there seems to be a zombie tribble clinging to your head, for it is scarfing your brain
|
||
|
|
0
|
|
|
#17 | ||||
|
To the OP: You've received several partially correct and blatantly wrong replies. People have tried to talk about the equivalence between arrays and pointers, and as is often the case, they've gotten it wrong. You cited the C FAQ; read chapter 6, "Arrays and Pointers" for the truth about that, and I suggest everyone who's posted here do the same. In particular, the claim that "arrays are constant pointers" should be ignored, because it is completely wrong. Hopefully everyone will go read the FAQ instead of trying to argue about this now, but long experience means I'm not optimistic about that.
![]() Quote:
Code:
char (*p)[];
void f()
{
p[1][0];
}
Code:
#define M 10 #define N 20 char b[M][N]; char (*p)[N] = b; Quote:
Code:
void f(char** p); void f(char* p[]); void f(char* p[2]); void f(char* p[200]); Code:
void f(int); Again, it is beyond evil for the array syntax to work like this in this one context. It can take a long time to undo the damage it does to one's mind. Elsewhere, your incomplete type means something completely different. For example: Code:
char* b[];
int main()
{
b[0] = 0;
}
Code:
char* b[];
char* b[10];
int main()
{
b[0] = 0;
}
In general, incomplete types are most used in forward declarations, for example, declaring pointers to types that cannot be completed until sometime later: Code:
struct S;
struct T
{
struct S* s; // S is incomplete here
};
struct S
{
struct T t; // T has to be complete for this to work.
};
Quote:
![]() Quote:
Arrays are not pointers. They don't contain pointers. For example, there is not a single pointer anywhere in or around int[10], int[10][20], int[10][20][30], etc. An array is an area of storage containing elements of a single type, one after the other, with no space in between them. There is a standard conversion employed in most contexts called the array-to-pointer conversion that produces a pointer to an array's first element given the array's name. It is from this conversion that the pointer-like behavior of arrays arises. For example, when you say b[2] for some array b, it is converted to *(b+2) per the array indexing rules, and b undergoes the array-to-pointer conversion, producing a pointer to b's first element. While similar to saying p[2], where p is an actual pointer pointing to b's first element, the difference is, the compiler had to fetch the contents of the pointer p to compute the address p+2, whereas it "knows" where the array b starts in memory, so there is no runtime fetching of a pointer value to compute the address b+2. Here are a couple of examples of array types and the types of their first elements: Code:
int a1[10]; int* p1 = a1; int a2[10][20]; int (*p2)[20] = a2; Code:
int** p2 = a2; // Bad!
Last edited by jon3543; Jan 9, 2013 at 12:32 AM. |
|||||
|
|
0
|
|
|
#18 |
|
The confusion arises from the fact that the syntax for accessing a primitive array can be the same whether the array is statically allocated or an arbitrary location designated by a pointer. For a pointer, the term *ptr is exactly equivalent to ptr[0], which is the same phrasing one uses with a statically allocated array. Similarly, if you have an indirect pointer (e.g., "int **indirectPtr"), you can use the index phrasing in place of the indirection operator: "**indirectPtr" is exactly equivalent to "indirectPtr[0][0]". In a very real sense, any variable label can be thought of as a sort of symbolic pointer because it designates a location in memory (and its location can be obtained with the "&" operator).
What the OP should learn from this confusion is the value of using typedef s. Most serious programmers do not use constructions that are difficult to comprehend because they want code that is easy to maintain.
__________________
Mr. Paul, sir, I thought you should be advised, there seems to be a zombie tribble clinging to your head, for it is scarfing your brain
|
|
|
|
0
|
|
|
#19 | |
|
Quote:
Code:
typedef char* CharPtr; // Now define a pointer to const char using CharPtr. Most people will try: const CharPtr p; // Wrong! // The above is equivalent to CharPtr const p; and thus char* const p; // There's no way to do do it. You have to define another typedef // basically from scratch: typedef const char* ConstCharPtr; ConstCharPtr p; // Or you can just eschew typedefs altogether for this, which many prefer: char* p1; const char* p2; // Someone who really knows his stuff and is on his game would actually prefer: char const* p3; // And he wouldn't have made the initial mistake, because he would have written it as: CharPtr const p4; // And he would know that defines a const CharPtr, not a pointer to a const char, // and he'd realize the latter is impossible to achieve with CharPtr. The advantage // of placing the cv-qualifiers like this is apparent if you read the declarations // aloud from right-to-left, e.g. "p3 is a pointer to const char", and // "p4 is a const CharPtr". It allows you to legitimately replace CharPtr // with its definition and say, "p4 is a const pointer to char". |
||
|
|
0
|
|
|
#20 |
|
And yet I've been programming using 'C' since '82 and I far and away prefer to use user defined types than not - personal preferences.
|
|
|
|
0
|
|
|
#21 |
|
Except any variable declared with the register keyword which has no memory address since it is stored in a CPU register (assuming the compiler actually decides to do what you have told it to do).
__________________
Neural Advance - Mac OS X, UNIX and Windows Development Last.fm Profile | Extreme Metal Reviews MP 4x 2.66Ghz Xeons / 6GB RAM / 640GB + 500GB + 750GB + 1TB HDDs / ATI Radeon 4870 / iPad 3 |
|
|
|
0
|
|
|
#22 | |
|
Quote:
So, that's either a very well-crafted troll, or you really do think it was a meaningful comment. Either way, there's probably not much point in my responding to it in any depth. Instead, having already written a couple of messages that discussed a number of things in depth, I'll just respond to your message with one containing exactly as much content, no more, no less, "I've been eating pie since 1970. I far and away prefer it to cake - personal preference."
Last edited by jon3543; Jan 9, 2013 at 04:25 PM. |
||
|
|
0
|
|
|
#23 |
|
That wasn't my intent at all. It was to point out how silly your statement seemed!
In other words I'm not an idiot, you're not idiot and you shouldn't assume someone who does thing differently then you is an idiot either. Last edited by lloyddean; Jan 9, 2013 at 05:29 PM. |
|
|
|
0
|
|
|
#24 | ||
|
Quote:
Quote:
|
|||
|
|
0
|
|
|
#25 |
|
It has no obligation to, as the register keyword is "just a hint" (which is actually commonly ignored). In fact, the other way around is also true: The compiler may well decide to keep something in a register when the optimizer thinks that's a good idea, even if you didn't mention the register keyword.
__________________
Computer Programming: An Introduction for the Scientifically Inclined So how much does an iPhone developer make? My iPhone games: Sjoelen, Mazer (free) |
|
|
|
0
|
![]() |
|
«
Previous Thread
|
Next Thread
»
| Thread Tools | Search this Thread |
| Display Modes | |
|
|
All times are GMT -5. The time now is 04:46 PM.









Linear Mode
