I usually see the syntax for malloc allocation :
int **p = malloc(N*sizeof(int*))
with p being a pointer. I have also seen the following syntax (maybe my sources are not right) :
int **p = malloc(N*sizeof(*int))
The difference between 2 syntax above is that "star" * appears after the type int for the first and before for the second one.
Could you tell me the right syntax between the two above?
The second one can be used only with an expression as the operand of the sizeof operator (and *int is not an expression, it's a syntax error).
You probably have seen it in code that uses the canonical way to allocate a dynamic array of N members of an arbitrary type:
p = malloc (N * sizeof *p);
I deliberately do not show the declaration of the pointer type p, since it is not needed. Even if the type of p changes, you never need to touch this allocation line. It always does the right thing.
C grammar sizeof quirk: with an expression operand, the parentheses are optional. They are required when the operand is a type.
None of the above is right for enough amount of memory. Below is correct:
int *p = malloc(N * sizeof(int));
or
int **p = malloc(N * sizeof(int *));
In the first one, you allocate memory for integers and you return it as pointer. The second is allocating array of pointers so you need * character in sizeof keyword.
But for messing in future of sizes, if you change int *p to let's say char *p, it is better to use this syntax:
int *p = malloc(N * sizeof(*p));
TL;DR The first one, partially (considering you have the terminating ; in your actual code).
Probably a better Correct way to write it will be
int *p = malloc(N*sizeof(*p)); // need memory for "int" type, not pointer to int
which removes the hard-coded dependency on the data type.
FWIW, the second one,
int *p = malloc(N*sizeof(*int))
is an erroneous statement, syntactical error.
And, to nitpick, it's not a "star", it's called a dereference operator.
Related
Until now I did allocate the memory for a matrix like this :
int **p,n;
scanf("%d",&n);
p=malloc(n*sizeof(int));
for(int i=0;i<n;i++)
p[i]=malloc(n*sizeof(int));
but someone told me to do like this :
int **p,n;
scanf("%d",&n);
p=malloc(n*sizeof*p);
for(int i=0;i<n;i++)
p[i]=malloc(n*sizeof*p);
sizeof(p) is not 0 because is not allocated ??
Which one is good ?
In the first code snippet, this statement is wrong:
p=malloc(n*sizeof(int));
because the type of p is int **, so, p can be pointer to a int *
type. It should be:
p = malloc (n * sizeof (int *));
^^^^^
In the second code snippet, allocation to p is correct because of this - sizeof*p. The type of *p is int *. So, sizeof*p is equivalent to sizeof (int *).
But in second code snippet, this is wrong:
p[i]=malloc(n*sizeof*p);
because the type of p[i] is int * i.e. pointer to an int. So, it can point to an integer. Hence, you should allocate memory of n * sizeof (int). It should be
p[i] = malloc (n * sizeof *p[i]);
Here, n * sizeof *p[i] is equivalent to n * sizeof (int) because the type of *p[i] is int.
Its matter of choice to use whichever style you want to. The matter of fact is that, you should have a good understanding of what you are doing and how it works because the lack of understanding can result in mistake in any style that you choose (as you can see there is mistake in both the code snippets you have shown).
First of all, p=malloc(n*sizeof(int)); is wrong - you aren't allocating a 2D array but an array of pointers, each pointing to an array of int. This needs to be p=malloc(n*sizeof(int*)); for the first example to be correct.
Apart from that bug, this is a matter of subjective coding style. Some prefer to write malloc(n*sizeof*p); since sizeof *p gives the size of the pointed-at item. This works because sizeof isn't evaluated for side effects, so no pointer de-referencing actually happens. The size is computed at compile-time.
A third style is also possible: p=malloc( sizeof(int*[n]) );. Here you make it more explicit that you are declaring an array. Which of these three styles to use is subjective and mostly a matter of opinion.
And in case you want to allocate actual 2D arrays allocated adjacently, you need to do as advised here instead: Correctly allocating multi-dimensional arrays
char c[] = {'a','b','c'};
int* p = &c[0];
printf("%i\n", sizeof(*p)); //Prints out 4
printf("%i\n", sizeof(*c)); //Prints out 1
I am extremely confused about this section of code. Both p and c represent the address of the array c at the 0th index. But why does sizeof(*p) print out 4? Shouldn't it be 1?
Because p is of type int *, so *p is of type int, which is apparently 4 bytes wide on your implementation.
And use %zu for printing size_t (what sizeof yields) if you don't want your program to invoke undefined behavior.
sizeof(*p) is the size of the int object to which p points.
sizeof(*p) will print size of p which is 4 because of int but c is of char that's why it is 1
In C (not C99) the sizeof operator is strictly a compile time calculation. so when sizeof (*p) [a dereferenced ptr to an integer] is evaluated then the size of int is four.
Note. the (*p) portion of that statement is a "cast" operator. So, sizeof is NOT a function call as in sizeof(xyz), rather it is like sizeof var_name or sizeof (int *).
When your program runs it changes the object pointed to by p, but the value of sizeof (*p) was already computed and hard-coded into your executable load module.
I think your confusion is that you were thinking that C would figure out what data type p was pointing to when your program runs.
I'm trying to document some code to improve my knowledge of pointers and general ANSI C ability.
...
int static_store = 30;
const char * pcg = "String Literal";
int main()
{
int auto_store = 40;
char auto_string[] = "Auto char Array";
int * pi;
char * pcl;
pi = (int *) malloc(sizeof(int));
*pi = 35;
pcl = (char *) malloc(strlen("Dynamic String") + 1);
strcpy(pcl, "Dynamic String");
...
From first looks, two pointers are initialised, pi and pcl, of type int and char respectively.
But the lines after are confusing to me and I don't understand what is happening. I can see that malloc is being called to allocate memory the size of int (40). Is it assigning memory to the variables pi and pcl?
Is it assigning memory to the variables pi and pcl?
Yes malloc is allocating memory to these pointers.
pi is allocated memory equal to sizeof(int)(that may vary) and pcl has be allocated memory equal to length of string plus 1(plus 1 for null character).
From first looks, two pointers are initialised, pi and pcl, of type int and char respectively
They are declared not initialized.
Note- Please don't cast return of malloc
2 pointers are delcared (pi and pcl). At declaration they are not intialized.
pi is then pointed to a block of heap allocated memory that can hold 1 int (the size of this is platform dependant but it would usually be 4 bytes) allocated with the fucntion maloc. Somewhere this memory will have to be explicitely freed with the funtion free - failing to do so will be a memory leak.
The int value 35 is then stored at that memory location. *pi can be read as "what the pointer pi points to" it is effectively the same as pi[0].
pcl is then pointed to a block of heap allocated memory that is large enough to hold 14 char plus a '\0' char (i.e 15 bytes) using the function malloc (as above at some point this memory must be freed).
The 15 characters "Dynamic String\0" is then put in that memory using the function strcpy.
The line:
pi = (int *) malloc(sizeof(int))
Actually allocate memory for one int variable. The line afterwards, puts the value 35 into that variable.
The line:
pcl = (char *) malloc(strlen("Dynamic String") + 1)
Creates a dynamically allocated char array (which is equivalent to a string). The size of that array is of the length of the string ("Dynamic String") plus one. The next line copies the string: "Dynamic String" into the allocated array. The plus one is needed because each string in c ends with the char '\0' which is a sign for the end of a string.
The malloc function reserves a block of memory in the heap (the dynamic memory pool), and returns a pointer to the first element of that block of memory. That memory is reserved until you call free, or the program exits.
In the call
pi = (int *) malloc(sizeof(int));
malloc reserves a block of memory large enough to store a single int value, and the pointer to that memory block is assigned to pi. You do not need to cast the result of malloc1, and it's actually considered bad practice2. A better way to write that would be
pi = malloc( sizeof *pi );
The expression *pi has type int, so sizeof *pi is equivalent to sizeof (int)3. The advantage of using sizeof *pi over sizeof (int) (as well as dropping the cast) is that if you ever change the type of pi (from int * to long *, for example), you won't have to change anything in the malloc call; it will always allocate the right amount of memory regardless of the type of pi. It's one less maintenance headache to worry about.
Similarly, the call
pcl = (char *) malloc(strlen("Dynamic String") + 1);
reserves enough memory to hold the contents of "Dynamic String" (the +1 is necessary for the string terminator) and assigns the pointer to that memory to pcl. Again, this would be better written as
pcl = malloc( strlen("Dynamic String") + 1 ); // no cast
sizeof (char) is 1 by definition, so you don't need an explicit sizeof *pcl in the call above; however, if you ever decide to change the type of pcl from char * to wchar_t *, it would be good to have it in place, although you'd still have to change the string literal and change how you compute the length, so it's not maintenance-free.
The general form a malloc call is
T *p = malloc( num_elements * sizeof *p ); // where num_elements > 1
or
T *p;
...
p = malloc( num_elements * sizeof *p );
There is a similar function named calloc that will zero out the allocated memory block:
T *p = calloc( num_elements, sizeof *p );
or
T *p;
...
p = calloc( num_elements, sizeof *p );
1. In C, anyway; C++ does require the cast, since C++ does not allow implicit conversions between void * and other pointer types. But you shouldn't be using malloc in C++ code, anyway.
So why do people still cast the result of malloc in C? It's largely a holdover from pre-ANSI days (more than a quarter of a century ago), when malloc returned char *, which cannot be assigned to a different pointer type without a cast. The 1989 standard introduced the void * type, which is essentially a "generic" pointer that can be assigned to other pointer types without an explicit cast.
2. Under the C89 standard, if the compiler sees a function call without having seen a declaration for that function, it will assume that the function returns int. Thus, if you forget to include stdlib.h or otherwise don't have a declaration for malloc in scope, the compiler will assume it returns an int value and generate the machine code for the call accordingly. However, int and pointer types aren't compatible, and normally the compiler will issue diagnostic if you try to assign one to the other. By using the cast, however, you supress that diagnostic, and you may run into runtime problems later on.
The 1999 standard did away with implicit int typing for functions, so that's not really a problem anymore, but the cast is still unnecessary and leads to maintenance problems.
3. sizeof is an operator, not a function; parentheses are only required if the operand is a type name like int or double or struct blah.
I'm still struggling to get comfortable with pointers. Not the concept - I understand memory locations, pointer increments matching variable length, etc - it's the syntax. Here's an example that I think is one reason I get confused/can't get an intuitive grip on it:
int a = 42;
Allocates and puts 42 in an int-sized memory space
int *pa = &a;
Allocates a pointer in memory that points to the address containing the variable "a".
printf("%d \n", *pa);
Prints 42.
Simple/basic. What bothers me is that:
int *pa = &a;
Would seem to indicate that *pa and &a are equal; equal to the memory address of a. But in:
printf("%d \n", *pa);
*pa is the contents of the address pa points to. So *pa appears to be two different things (address or int) depending on context. And makes me concerned that "=" != "=".
Now I'm not trying to complain about/redefine/question the language, I'm just wondering if anyone has any tips that will help me understand this better, make it make more intuitive sense. I assume it makes perfect logical sense if you really know the language; I'm hoping someone can explain it so it seems logical to me, too.
int * is not the same as the * in printf("%d \n", *pa);.
Specifically, int *, the entire thing, is basically a type: A "pointer to an int" type.
In other words, int * is a type.
However, invoking *pa means to dereference the pointer pa. So, * is an operator: the deference operator.
Also, to be pedantic, = is actually the assignment operator.
Three general cases for *:
Pointer type. * will follow a type. Example: int * is the pointer-to-an-int type.
Dereference operator. This is a unary operator, and dereferences a pointer to get the "underlying value" in the memory address.
Multiplication operator. This is a binary operator.
Your confusion seems to be because you initialize and declare the pa pointer at the same time, see this
int a = 42;
int *pa;
pa = &a;
now *pa and &a do not seem to be equal.
In C, there are 3 main uses of the * symbol. It takes place as part of a type, a unary operator, and an arithmetic operator.
The first case, as part of a type is used to initialize a pointer. int* foo means that foo is a pointer to an integer, that means foo holds the address of a pointer.
Ex int* pa = &a, pa == address of a.
The second case, as a unary operator is called the dereferencing operator. Unary is when the * has only a value on it's right. Like this it will act as a dereferencing operator. Dereferencing is expressing the value at a given address.
Ex following from the previous example
pa = &a
if (*pa == 1) Look at what value is at the address p is holding
The third case is trivial, but worth mentioning in how it differs from how it acts as a unary operator. As an arithmetic operator, it needs a value to the left and the right.
Exint x = 5 * 5
TL;DR In int *pa, the * is part of the type, not the variable. It might be more clear to see it as int* pa. When it is not a part of a type, the * is a dereferencing operator, meaning to look at the value present at that address.
It might make more intuitive sense if you used a syntax that explicitly shows pa as a variable with a different type than a. This can be accomplished with simple spacing:
int a = 42;
int* pa = &a;
printf("%d", *pa);
Note that all I've done here is shifted the spacing in the declaration of pa so that the * is attached to its type rather than the variable itself.
Mind you, I do think that the syntax can be construed as confusing - it wouldn't be the first confusing thing about C. Personally I might have preferred the use of something like ! for dereferencing:
int a = 42;
int* pa = &a;
printf ("%d", !pa); /* this is fantasy C */
Of course, then you'd have to come up with something else for logical not...
In C, I am having a structure like this
typedef struct
{
char *msg1;
char *msg2;
.
.
char *msgN;
}some_struct;
some_struct struct1;
some_struct *pstruct1 = &struct1;
I want to keep a pointer or a varible which when incremented or decremented, gives the next/last member variable of this structure. I do not want to use array of char * since it is already designed like this.
I tried using the union and structure combination, but I don't know how to write code for that.
Thought iterator may help but this is C.
Any suggestions ?
You can't do that, safely. You can take a chance that the adjacent character pointers are really adjacent (with no padding) as if they were in an array, but you can't be sure so that's pretty much straight into the undefined behavior minefield.
You can abstract it to an index, and do something like:
char * get_pointer(some_struct *p, int index)
{
if(index == 0)
return p->msg1;
if(index == 1)
return p->msg2;
/* and so on */
return NULL;
}
Then you get to work with an index which you can increment/decrement freely, and just call get_pointer() to map it to a message pointer when needed.
You can do this using strict C, but you need to take certain precautions to ensure compliance with the standard. I will explain these below, but the precautions you need to take are:
(0) Ensure there is no padding by including this declaration:
extern int CompileTimeAssert[
sizeof(some_struct) == NumberOfMembers * sizeof(char *) ? 1 : -1];
(1) Initialize the pointer from the address of the structure, not the address of a member:
char **p = (char **) (char *) &struct1;
(I suspect the above is not necessary, but I would have to insert more reasoning from the C standard.)
(2) Increment the pointer in the following way, instead of using ++ or adding one:
p = (char **) ((char *) p + sizeof(char *));
Here are explanations.
The declaration in (0) acts as a compile-time assertion. If there is no padding in the struct, then the size of the struct equals the number of members multiplied by the size of a member. Then the ternary operator evaluates to 1, the declaration is valid, and the compiler proceeds. If there is padding, the sizes are not equal, the ternary operator evaluates to -1, and the declaration is invalid because an array cannot have a negative size. Then the compiler reports an error and terminates.
Thus, a program containing this declaration will compile only if the struct does not have padding. Additionally, the declaration will not consume any space (it only declares an array that is never defined), and it may be repeated with other expressions (that evaluate to an array size of 1 if their condition is true), so different assertions may be tested with the same array name.
Items (1) and (2) deal with the problem that pointer arithmetic is normally guaranteed to work only within arrays (including a notional sentinel element at the end) (per C 2011 6.5.6 8). However, the C standard makes special guarantees for character types, in C 2011 6.3.2.3 7. A pointer to the struct may be converted to a pointer to a character type, and it will yield a pointer to the lowest addressed byte of the struct. Successive increments of the result, up to the size of the object, yield pointers to the remaining bytes of the object.
In (1), we know from C 2011 6.3.2.3 7, that (char *) &struct1 is a pointer to the first byte of struct1. When converted to (char **), it must be a pointer to the first member of struct1 (in particular thanks to C 2011 6.5.9 6, which guarantees that equal pointers point to the same object, even if they have different types).
Finally, (2) works around the fact that array arithmetic is not directly guaranteed to work on our pointer. That is, p++ would be incrementing a pointer that is not strictly in an array, so the arithmetic is not guaranteed by 6.5.6 8. So we convert it to a char *, for which increments are guaranteed to work by 6.3.2.3 7, we increment it four times, and we convert it back to char **. This must yield a pointer to the next member, since there is no padding.
One might claim that adding the size of char ** (say 4) is not the same as four increments of one char, but certainly the intent of the standard is to allow one to address the bytes of an object in a reasonable way. However, if you want to avoid even this criticism, you can change + sizeof(char *) to be +1+1+1+1 (on implementations where the size is 4) or +1+1+1+1+1+1+1+1 (where it is 8).
Take the address of the first member and store it to char **:
char **first = &struct1.msg1;
char **last = &struct1.msg1 + sizeof(some_struct) / sizeof(char *) - 1;
char **ptr = first; /* *ptr is struct.msg1 */
++ptr; /* now *ptr is struct1.msg2 */
This assumes that the structure only contains char * members.