I am running this piece of code on a hardware.
unsigned char *buf;
buf = malloc(sizeof(int));
printf("Address of buf %d\n" , &buf);
if(!buf)
return MEMORYALLOC_FAILURE;
The malloc is returning negative value. What could be the problem?
Address returned by malloc is not negative or positive, it just address, use %p to print it, not %d:
printf("Address of buf %p\n" , &buf);
And if you want to print the address returned from malloc, remove the ampersand:
printf("Address of buf %p\n" , buf);
You're printing the address of a memory location as a signed integer. If the memory address--for example on a 32bit machine--is more than 2,147,483,647 (0x7FFFFFFF) it will display as a negative number.
In this case you're also printing the address of a local variable on the stack rather than the address returned by malloc.
The error with using %d to print a pointer-sized value is that pointers may vary in size. The correct approach therefore would be to use the printf specifier for pointers, %p:
// nb: we don't take the address of buf,
// buf is already a pointer (thus its *value* is an address)
printf("Address of buf %p\n", buf);
Type mismatch:
you try to print an address with the specifier for an int ("%d"). You should use "%p" and cast the value to void*
printf("Address of buf %p\n" , (void*)&buf);
Also note the above will not tell you where the allocated memory is. For that you'd need
printf("Address of newly allocated memory %p\n" , (void*)buf);
The cast to void* is mandated by the C99 standard (emphasis is mine)
The argument shall be a pointer to void. The value of the pointer is converted to a sequence of printing characters, in an implementation-defined manner.
Also note that pointers to void need not have the same representation as pointers to other types.
malloc returns either NULL (aka 0) or a memory address. Memory addresses cannot be negative. You just converted the pointer itself to a number, resulting in a negative number.
malloc returns a pointer. It never returns a negative value. If you think it is then you probably have a broken everything. On the other hand if you mean it returns a null pointer, then it means you are unable to allocate that memory.
Related
I'm new to C and currently learning about Pointers. All I know is a pointer is basically a variable that contains the address of another variable and to get its data we need dereference pointer :
int i = 10;
int *pi = &i;
printf("%d",*pi);
But watching some tutorials on yt I also see
char *p = "Hello";
printf("%s",p); //print out Hello//
I also test it myself
int *i = 10;
printf("%d",i); //print out 10//
I have searched about it and know it's a kind of read-only memory instead of char []. But p and i here are pointers and how can they work with %s and %d directly but not dereferencing *i *p. Can anyone explain it to me pls.
A pointer doesn't necessarily contain address of another variable, it contains an address of some data, which can but doesn't need to be in a variable. For example, the pointer may point to dynamically allocated data, or to data that is part of an array, or to static data that ships with the executable.
In case of char *p = "hello", p points to the first character of a character array prepared by the compiler, and which contains the letters hello followed by a terminating zero character. The %s specifier is designed to receive such a pointer and print the letters up to the zero character, which is why it works.
Your second example, where you print a pointer using %d is quite different in nature. It abuses the fact that addresses have integer representations, and that T *x = <some integer> implicitly casts the integer to the corresponding memory address. In your case you create an invalid pointer pointing to the invalid address 10. Then you proceed to call printf with the %d specifier without dereferencing the pointer. Since %d expects an integer, and the address is also internally represented as an integer, this prints the invalid address 10 the pointer points to. However, pointers and integers don't have compatible memory representations, so this kind of code only works by accident, and exhibits undefined behavior.
To generalize the answers already given, a pointer is simply a variable that contains a memory address. How the code attempts to use that memory address depends on the context you give to it. A pointer can point to data, or even code, in the form of a function pointer. You could even assign any arbitrary value you want to a pointer, and the code will attempt to use it, though that likely will fail or give unpredictable results.
It's perfectly legal to do this:
int *i = (int *)0x12345678;
and dereferencing that pointer (int x = *i;) is also perfectly legal, but will almost certainly fail, because 0x12345678 is likely not an address that is valid when your code runs. Even if it is, the code generated by the C compiler will attempt to access those bytes in a manner that may not correspond to whatever is stored there. In the above case, if you're on, say, a 32-bit x86, the code will interpret the 4 bytes starting at 0x12345678 as a 32-bit signed integer in little-endian format. Whatever is actually there may not result in a usable value.
hi Have Following Have Example Of Pointer With Array
enter code here
#include<stdio.h>
#include<conio.h>
void main()
{
int x,*px,i,**pxx;
x=10;
px=&x; //Right Way To iniFor Pointer
pxx=&px+1; //store address of another pointer
clrscr();//we use px+1 because have 2 address 1 is x and 2 px
printf("\n\n passed value of x in pointer");
printf("\n\n the value of x:-%d",x);
printf("\n the value of px:-%d",*px);//Using * u access a value
printf("\n the value of pxx:-%d",**pxx);
printf("\n\n the address of pointer variable");
printf("\n\n the &x address:-%p",&x);
printf("\n the px &address:-%p",&px); //using %p Or %x Acces address
printf("\n The address of pxx:%p",&pxx);
for(i=0;i<5;i++)
{
px=px+1;
*px=i;
printf("\n%d %p",*px,px);
}
printf ("\n\nThe array of Pointer\n");
for(i=0;i<5;i++)
{
pxx=pxx+1;
printf("\n%d %p",*pxx,pxx);
}
getch();
}
in this example pointer used as a array
**pxx is have 2 address 1 is x 2 is pxx
that reason we used pxx=&px+1 to access address of px
*-represents value at certain variable.
&-represents address of certain variable.
*p=10 let's say the address of p might be "662543" so now by you have stored the value 10 in the address "662543".
and nor if you print
*p - output will be 10, and
&p- output will be 662543.
and talking about the % sign its a format specifier. like %d for integer, %f for float and %s for string etc.
and difference between %d and %i is as follows-
%d takes integer value as signed decimal integer i.e. it takes negative values along with positive values but values should be in decimal otherwise it will print garbage value.( Note: if input is in octal format like:012 then %d will ignore 0 and take input as 12) Consider a following example.
%i takes integer value as integer value with decimal, hexadecimal or octal type.
To enter a value in hexadecimal format – value should be provided by preceding “0x” and value in octal format – value should be provided by preceding “0”.
Why is the operator (*) needed to access the value of an int* variable but not for char*?
char *char_ptr;
int *int_ptr;
int mem_size = 50;
char_ptr = (char *) malloc(mem_size);
strcpy(char_ptr, "This is memory is located on the heap.");
printf("char_ptr (%p) --> '%s'\n", char_ptr, char_ptr);
int_ptr = (int *) malloc(12);
*int_ptr = 31337;
printf("int_ptr (%p) --> %d\n", int_ptr, *int_ptr);
Output:
char_ptr (0x8742008) --> 'This is memory is located on the heap.'
int_ptr (0x8742040) --> 31337
This is because of the way the printf format specifiers work: the %s format expects, for its corresponding argument, a pointer to a character (more precisely, the address of a nul-terminated string - which can be an array of char, an allocated buffer with at least one zero byte in it, or a string literal), so you can just give it the char_ptr variable as-is; on the other hand, the %d format expects an integer (not a pointer-to-integer), so you have to dereference the int_ptr variable using the * operator.
Note on Good Programming Style: As mentioned in the comments to your question, be sure to call free() at some point on every buffer allocated with malloc, or you will introduce memory leaks into your code. Also see: Do I cast the result of malloc?.
You also can use the expression *char_ptr. It has the type char and the expression will yield the pointed character that is 'T' - the first character of the stored string literal.
This is the same as *int_ptr that returns the first element of the allocated integer array.
As for the conversion specifier %s then it expects an argument of the type char * that points to a string. On the other hand, the conversion specifier %d expects an object of the type int
You could use the conversion specifier %c. to output just a single character of the pointed string like
printf( "%c", *char_ptr );
For any pointer or array p and index i, the expression p[i] is exactly equal to *(p + i). From that follows that *p is equal to p[0].
In your case *int_ptr is equal to int_ptr[0].
If you did the same with char_ptr (i.e. *char_ptr) you would have char_ptr[0] which is a single character, that could be printed with %d as well:
printf("char_ptr (%p) --> '%d'\n", char_ptr, *char_ptr);
This would print the decimal representation of the first character in the string.
"Why is operator (*) needed to access the value of an int* variable and not for char* ?"
Because at the printf() function, the format specifier %s expects a matching argument of type char * - a pointer to a string, while %d expects an argument of type int.
In the latter case, the dereference operator * is required to dereference int_ptr and yield the value of the int object int_ptr points to.
As char_ptr is already of type char* as required by %s, there is no need to dereference it.
Side notes:
1.
int_ptr = (int *) malloc(12);
Note that with 12 Bytes on most modern system you be able to allocate only 1 int object as it requires 8 Byte. The remaining 4 Byte are not sufficient to hold another.
If you want to allocate space for only one int, use sizeof(*int_ptr):
int_ptr = (*int) malloc(sizeof(*int_ptr));
2.
Also don´t forget to free() the storage allocated by malloc() after its use:
free(int_ptr);
free(char_ptr);
3.
Furthermore there is no need to cast the return value of malloc(): Do I cast the result of malloc?
char_ptr = malloc(mem_size);
int_ptr = malloc(sizeof(*int_ptr));
int *ptr;
ptr=(int *)malloc(sizeof(int)*2);
ptr=100; /*What will happen if I put an asterisk(*) indicating *ptr=100? */
ptr++;
printf("ptr=%d",*ptr);
free(ptr);
So, I wanted the pointer to increment. I allocated a size of 4(2*2) for the pointer. But I couldn't understand how the pointer increments only by 2. And if I put an asterisk int the 3rd line,that is *ptr=100; It shows something else.
If you have int * ptr, then ptr++ increments the pointer by the size of a single int. If int is two bytes on your platform, that's why it increments by two.
*ptr = 100 would store the value 100 at the int pointed to by ptr, i.e. the first of the two ints that you allocated with your malloc() call.
ptr = 100 will attempt to assign the memory address 100 to ptr, which is almost certainly not what you want, as you would lose your reference to the memory you just malloc()ed, and what is at memory location 100 is probably not meaningful for you or accessible to you.
As it currently stands, if you were to do *ptr = 100 and then ptr++, your printf() call would result in undefined behavior since you'd have incremented the pointer to point to uninitialized memory (i.e. the second of the two ints you allocated with your malloc() call), whose contents you then attempt to output.
(*ptr)++ on the other hand would increment that 100 value to 101, leave the value of ptr unchanged, your printf() call would be fine, and output 101. The second of the two ints you allocate would still remain uninitialized, but that's no problem if you don't attempt to access it.
Also, don't cast the return from malloc(), ptr=(int *)malloc(sizeof(int)*2) should be ptr=malloc(sizeof(int)*2), or even better, ptr = malloc(sizeof(*ptr) * 2);
Try this:
int *ptr;
ptr = malloc(2 * sizeof *ptr);
printf("ptr = %p.\n", (void *) ptr); // Examine pointer before increment.
ptr++;
printf("ptr = %p.\n", (void *) ptr); // Examine pointer after increment.
You will see that the value of ptr is incremented by the number of bytes in an int. The C language automatically does pointer arithmetic in units of the pointed-to element. So a single increment of an int pointer in C becomes, at the machine level, an increment of the number of bytes of an int.
Notes
%p is the proper specifier to use when printing a pointer, not %d. Also, the pointer must be cast to void * or const void *.
ptr = malloc(2 * sizeof *ptr); is a cleaner way to allocate memory and assign a pointer than your original code, because:
Using sizeof *ptr causes the code to automatically adapt if you ever change the type of ptr. Instead of having to change the type in two places (where ptr is declared and where malloc is called), one change suffices. This reduces opportunities for errors.
malloc does not need to be cast to the destination type. It returns a void *, which C will automatically convert to the destination type of the assignment without complaint. (C++ is different.) It will still work if you cast it, but this can mask another problem: If you accidentally do not declare malloc (as by failing to include <stdlib.h>, and compile in an old version of C, malloc will be implicitly declared to return an int, and the cast will mask the error. Leaving the expression without a cast will cause a warning message to be produced when this happens.
This line changes value of address in pointer to some nonsense (100 will not be any valid address):
ptr=100;
Then you increment the pointer to 100 + sizeof(int) because the pointer has type of int* which automatically increments address by amount of bytes to get to the next integer that ptr points to.
At next line you dereference the invalid pointer so your code should crash, but the command is ok if your pointer had valid address:
printf("ptr=%d",*ptr);
To repair your code just don't change the pointer itself but change the data:
int *ptr;
ptr=(int *)malloc(sizeof(int)*2);
*ptr=123; /*What will happen if I put an asterisk(*) indicating *ptr=100? */
printf("ptr=%d",*ptr);
ptr++;
*ptr=234;
printf("ptr+1=%d",*ptr);
// you can set or get your data also this way:
ptr[0] = 333;
ptr[1] = 444;
printf("ptr[0]=%d",ptr[0]);
printf("ptr[1]=%d",ptr[1]);
free(ptr);
First thing you need to understand is a POINTER points to ADDRESS, when your assign 100 to ptr, it means your pointer ptr now points to memory location whose address is 100.
Secondly pointer arithmetic depends on type of pointer, in your case ptr is a pointer pointing to integer. SO when you increment ptr, it means it will jump to the memory location of next integer. So, ptr gets incremented by 2 (memory occupied by one int on your platform)
To be simple
ptr=100;
By this you are trying to store a int as an address to a pointer, which Is nonsense.
In other words you are trying to make the pointer ptr to point the address 100, which is not an address.
But by
*ptr=100;
You are trying to store value 100 to the address pointed by ptr, which is valid.
Also
ptr++;
Means that now ptr is pointing to ptr+4 or (ptr+2 for 16 bit compiler like tc) address.
Also for your particular code, you are just changing and incrementing the address pointed by ptr, but you are not storing any value at the address pointed by ptr.
So your code will print garbage value or it may also crash as 100 is not a valid address.
Also you should have done
ptr=(int*)100;
It would remove
warning: assignment makes pointer from integer without a cast [enabled by default]
But still it is undefined behaviour.
I am using gcc and written a small program as under:
#include<stdio.h>
void doing(){
char buf[4096 + 1];
printf("buf %d\n", buf);
printf("buf %f\n", buf);
printf("buf %d\n", (unsigned) buf);
printf("buf %s\n", buf+2);
printf("buf %d\n", buf+2);
}
int main (void){
char buf[4096 + 1];
printf("(unsigned) buf %d\n", (unsigned) buf);
doing();
printf("(unsigned) buf %d\n", (unsigned) buf);
return 0;
}
The Output of the program is:
(unsigned) buf 2268303
buf 2264159
buf 0.000000
buf 2264159
buf
buf 2264161
(unsigned) buf 2268303
I don't know why printing 2268303 as integer and where from this 2268303 value comes and one function is giving the value as 2268303 and another 2264159
Let's break it down a bit and see what we can say about each line of code, one after the other:
int main (void){
char buf[4096 + 1];
You declare a char[4097], that is typically allocated on the stack by adjusting the stack pointer when main is entered. The contents of the array are indeterminate.
printf("(unsigned) buf %d\n", (unsigned) buf);
An expression of array type, unless it is the operand of the address (&), sizeof or _Alignof operators, or it is a string literal used to initialise a character array, is converted to a pointer to the array's first element (6.3.2.1 p. 3), so that line is equivalent to
printf("(unsigned) buf %d\n", (unsigned) &buf[0]);
takes the address of the first byte in buf, converts it to unsigned and prints the resulting number as a signed integer. Note that the behaviour is undefined if the resulting unsigned value is not representable as an int. The conversion of the pointer &buf[0] to unsigned is implementation-defined, and may invoke undefined behaviour (6.3.2.3 p. 6). Typically, sizeof(unsigned) bytes of the pointer value are interpreted as an unsigned integer (typically includes that the size of a pointer is not smaller than the size of an unsigned). In your case, the result was that
(unsigned) buf 2268303
was printed. Next
doing();
So let's look at doing:
void doing(){
char buf[4096 + 1];
Another char[4097] is declared, typically it is allocated by adjusting the stack pointer when doing is entered. The contents of this array are also indeterminate.
printf("buf %d\n", buf);
Again, the expression buf of type char[4097] is converted to a char*, namely &buf[0], and that is passed to printf which expects an int argument. The type mismatch invokes undefined behaviour, commonly sizeof(int) bytes of the pointer value are interpreted as a signed integer. The result is the ouptut
buf 2264159
which strongly hints that the buf in doing was allocated 4144 bytes away from main's and the stack grows downward.
printf("buf %f\n", buf);
Once again we have the array-to-pointer conversion, and now printf expects a double argument but gets a char*. More undefined behaviour, the manifestation is that
buf 0.000000
is printed. How that comes cannot be answered in general (after all, it's undefined behaviour), on 64-bit systems, a common behaviour is that printf arguments of pointer or integral types are passed in general purpose registers, and floating point arguments in floating point registers, so that printf would read a floating point register - which happens to contain a 0 value.
printf("buf %d\n", (unsigned) buf);
This line has the same semantics as the corresponding line of main, but since it's a different array buf, the (unsigned) integer obtained from the conversion is different.
buf 2264159
it prints the same as the first printf in doing, which is not surprising (but not guaranteed, since undefined behaviour is involved).
printf("buf %s\n", buf+2);
buf is converted to &buf[0], then 2 is added to that, resulting in &buf[2]. That is passed to printf, which, due to the %s conversion expects a pointer to a 0-terminated array of char as argument. This is the only printf call in the entire programme where the type of printf's second argument matches the type expected due to the conversion specifier exactly. But the contents of buf are indeterminate, so if there is no 0 byte in the array, that will cause invalid reads by printf. However, apparently buf[2] was 0, so just
buf
was printed.
printf("buf %d\n", buf+2);
buf + 2 again evaluates to &buf[2], and that is passed where printf expects an int. The type mismatch invokes undefined behaviour, but the output
buf 2264161
suggests that nothing nefarious happened, and since &buf[2] is two bytes behind &buf[0], the number printed is two larger than the number printed in doing's first printf.
}
Back to main:
printf("(unsigned) buf %d\n", (unsigned) buf);
That line is identical to the first printf call in main, so it has the same semantics, that was discussed above,
(unsigned) buf 2268303
and produces the same output.
return 0;
}
Please read C Basics. You will get your answer.
Regarding,
one function is giving the value as 2268303 and another 2264159
Observe that, one char buf[] is declared in main() and another one is in doing(). Both have different storage and both will work in their own scope. [Read Scope of variables in C]
If you use %p you will get hex values.
You also need to brush up on scope as well. Go through these links too.
(unsigned) buf 2268303 // You have defined this in main its a local array so it has
//2268303 as address. And for an array the array name acts as a
//pointer too
buf 2264159 // You have defined this in fn doing, it is local to that function
//and has a different address (it is a different array than the one
//in your main)
Here's the explanation:
This:
printf("buf %d\n", buf);
will print the address(memory position) of the first element on your "buf" array
This:
printf("buf %f\n", buf);
will try to read a float from the address of the first element on your "buf" array, printf probably returns zero because it doesn't know what to do with it.
This:
printf("buf %d\n", (unsigned) buf);
will do the same as the first printf since the address of "buf" is always greater or equal than zero.
This:
printf("buf %s\n", buf+2);
will try to read a float from the address of the first element on your "buf" array, printf probably returns an empty string because it doesn't know what to do with it.
Finally:
printf("buf %d\n", buf+2);
returns the position off the third element in you "buf" array
Important to notice:
the two "buf" arrays you declared (one inside main, the other inside doing()) are two distinct arrays even though you gave them the same name.
Inside doing() "buf" refers to the one you created there, inside main "buf" also refers to the one you created there. Thats the reason why you get two different addresses when printing from inside doing or main
I am doing some experiments to see how C allocates variables on the stack. I am getting some odd behavior with the following code. C appears to be growing the stack downward, so in the following example, the char c is allocated in the byte immediately before the short s. I then create an int pointer bigRandP and point it at the same location occupied by c, so the "int" it sees overlaps with the space on the stack occupied by s. I then try to assign something to the location referenced by the int pointer.
unsigned short nameSum = 0;
unsigned char smallRand = 0;
unsigned int* bigRandP;
//The "int" pointed to by iP should overlap s
bigRandP = (unsigned int*)(&smallRand);
printf("%p %p %p\n", &nameSum, &smallRand, bigRandP);
printf("%u %u %u\n", smallRand, nameSum, *bigRandP);
*bigRandP = 0;
printf("%p %p %p\n", &nameSum, &smallRand, bigRandP);
printf("%u %u %u\n", smallRand, nameSum, *bigRandP);
0028FF1A 0028FF19 0028FF19
0 0 419430400
0028FF1A 0028FF19 0028FF00
0 0 4210788
The printed results are interesting. Not only does the assignment fail (the int pointed to by bigRandP is not set to 0), the int pointer itself is silently relocated to point somewhere else further down the stack. What is going on? Is this the C compiler's way of keeping me from overwriting other variables with overlapping pointers?
bigRandP is a pointer to unsigned int.
You pointed it to an unsigned char object, then you modified the unsigned int object that bigRandP points to.
Apparently smallRand and bigRandP are stored close to each other in memory. By trying to modify sizeof (unsigned int) bytes of a 1-byte object, you clobbered part of the pointer object itself.
Bottom line: Your program's behavior is undefined.
Also, though this probably isn't related to the behavior you're seeing, the %p format requires a void* argument. If you want to print some other type of pointer, you should convert it to void*:
printf("%p %p %p\n", (void*)&nameSum, (void*)&smallRand, (void*)bigRandP);
It's likely to "work" with or without the casts on systems where all pointers have the same representation, but the version with the casts is more correct on all systems.