how to send integer number via sheared memory in linux - c

I am trying to send integer data via a shared memory in linux it works very well with string
const char *msg="hello";
but when I try this gives me error
const int *msg=25;
and when I try to print the contain of the address for string works
printf("%s",(char *) ptr);
but for this I have error
printf("%d",(int *)ptr);
and I try to write this but I give me the address not the contain of the address
printf("%d",*(int *)ptr);

In your code,
const int *msg=25;
is likely to produce weird result, as, you're assigning a pointer address to get a value 25 which is most likely to be an invalid address in respect to your program. It's most likely you don't intend to do that.
Instead, write
const int msg=25;
and use &msg to get the address of that variable.
FWIW, the above changes (note the plural form) will solve the issue with printf(), too, and, the casts are not required, anyway.

printf("%s",(char *) ptr);
The cast to char * is unneeded.
printf("%d",(int *)ptr);
In order to get the value the pointer is pointing to, use *. So you'd write:
printf("%d", *ptr);
Also dont assign raw addresses to pointers, because you (usually) dont know what is in that address. In your example, address 25 might be anything. Dereferencing that pointer will likely cause a segfault( https://en.wikipedia.org/wiki/Segmentation_fault)
So instead of that you should do this:
int a = 25;
int *addr = &a; /* addr contains the address of a */
To print addr:
printf("%p", addr);
Or if %p is unavailable for your compiler, use %u.

Related

What is the address of a pointer in C?

int main()
{
int *p;
printf("%p \n", &p);
printf("%p \n", p);
return 0;
}
By executing this code I am receiving the following output:
0x16b77f710
0x104683f4c
I expected to get the same memory address, because the &p id not referenced to any other variable.
Why i am getting two different memory address?
Thanks,
The pointer is a normal object having (in your case type of int *). It cant point to itself because the type of such pointer would have to be int **
*image stolen from internet.
A pointer is a variable like any other. It has an address, which is typically the address in memory where that variable sits.
Like any other variable, a pointer variable also has some data in it. For a pointer variable, that data is the address of some other variable, the variable at which the pointer points.
The address of a variable, and the contents of a variable, are two totally different things. They are almost never equal.
Try this program, in which I give your variable p something to point to:
int main()
{
int i = 5;
int *p = &i;
printf("p: %p, p's address: %p\n", p, &p);
printf("i: %d, i's address: %p\n", i, &i);
}
You should notice two things:
As in your first program, "p" and "p's address" will be different.
Whatever value you see for "p", it will be the same as "i's address".
The reason is that a pointer, when declared, does not point to itself by default. Simplified you can imagine it in such a way that a pointer occupies 2 memory cells. 1 memory cell has the virtual address where the pointer itself is located (&p in your case), the 2nd memory cell contains the virtual address where the pointer points to (p in your case).
Since memory cells retain their value when they are deallocated, the cell containing the destination address of your pointer still contains an obsolete value from another, already completed process.
You would have the same phenomenon if you declare a new integer variable and then print its value with printf, you will see that there will already be some number in the new variable that will appear completely random. This is also due to the fact that there is still an obsolete value in the corresponding memory cell.
Let assume there is random memory block for just understanding name it a. Now assume that p is pointing to that memory block.
&p returns the address of memory block where p is present.
p returns the address of memory block(&a) to the variable/memory block(a) which p is pointing.
So of course it will give different memory addresses.
I expected to get the same memory address, because the &p id not referenced to any other variable.
Pointer variables do not automatically point to themselves; if you don't explicitly initialize them, then their initial value will be indeterminate (or NULL, depending on how they are declared).
There's nothing magic about pointer variables - like any other scalar, they store some kind of value; it's just that in their case, that value is an address of another object.
If you really want p to store its own address, you'll have to do something like
p = (int *) &p;
The cast is necessary because the type of the expression &p is int **, and you can't assign a pointer value of one type to a variable of a different pointer type. But, pointers to different types are not guaranteed to have the same size, representation, or alignment. On modern commodity hardware like x86 you can probably count on int * and int ** having the same size and representation, just be aware that doesn't have to be the case everywhere.

Can we change the base address of an array through a pointer to array using brute force?

Somebody wrote the following C program and asked why gcc allows "to change the base address of an array". He was aware that the code is terrible but still wanted to know. I found the question interesting enough, because the relationship between arrays and pointers in C is subtle (behold the use of the address operator on the array! "Why would anybody do that?"), confusing and consequently often misunderstood. The question was deleted but I thought I ask it again, with proper context and -- as I hope -- a proper answer to go with it. Here is the original prog.
static char* abc = "kj";
void fn(char**s)
{
*s = abc;
}
int main()
{
char str[256];
fn(&str);
}
It compiles with gcc (with warnings), links and runs. What happens here? Can we change the base address of an array by taking its address, casting it to pointer to pointer (after all arrays are almost pointers in C, aren't they) and assigning to it?
It cannot work (even theoretically), because arrays are not pointers:
int arr[10]:
Amount of memory used is sizeof(int)*10 bytes
The values of arr and &arr are necessarily identical
arr points to a valid memory address, but cannot be set to point to another memory address
int* ptr = malloc(sizeof(int)*10):
Amount of memory used is sizeof(int*) + sizeof(int)*10 bytes
The values of ptr and &ptr are not necessarily identical (in fact, they are mostly different)
ptr can be set to point to both valid and invalid memory addresses, as many times as you will
The program doesn't change the "base address" of the array. It's not even trying to.
What you pass to fn is the address of a chunk of 256 characters in memory. It is numerically identical to the pointer which str would decay to in other expressions, only differently typed. Here, the array really stays an array -- applying the address operator to an array is one of the instances where an array does not decay to a pointer. Incrementing &str, for example, would increase it numerically by 256. This is important for multi dimensional arrays which, as we know, actually are one-dimensional arrays of arrays in C. Incrementing the first index of a "2-dimensional" array must advance the address to the start of the next "chunk" or "row".
Now the catch. As far as fn is concerned, the address you pass points to a location which contains another address. That is not true; it points to a sequence of characters. Printing that byte sequence interpreted as a pointer reveals the 'A' byte values, 65 or 0x41.
fn, however, thinking that the memory pointed to contains an address, overwrites it with the address where "kj" is residing in memory. Since there is enough memory allocated in str to hold an address, the assignment succeeds and results in a usable address at that location.
It should be noted that this is, of course, not guaranteed to work. The most common cause for failure should be alignment issues -- str is, I think, not required to be aligned properly for a pointer value. The standard mandates that arguments to functions must be assignment-compatible with the parameter declarations. Arbitrary pointer types cannot be assigned to each other (one needs to go through void pointers for that, or cast).
Edit: david.pfx pointed out that (even with a proper cast) the code invokes undefined behaviour. The standard requires access to objects through compatible lvalues (including referenced pointers) in section 6.5/7 of the latest public draft. When casting properly and compiling with gcc -fstrict-aliasing -Wstrict-aliasing=2 ... gcc warns about the "type punning". The rationale is that the compiler should be free to assume that incompatible pointers do not modify the same memory region; here it is not required to assume that fn changes the contents of str. This enables the compiler to optimize away reloads (e.g. from memory to register) which would otherwise be necessary. This will play a role with optimization; a likely example where a debugging session would fail to reproduce the error (namely if the program being debugged would be compiled without optimization for debugging purposes). That being said, I'd be surprised if a non-optimizing compiler would produce unexpected results here, so I let the rest of the answer stand as is.--
I have inserted a number of debug printfs to illustrate what's going on. A live example can be seen here: http://ideone.com/aL407L.
#include<stdio.h>
#include<string.h>
static char* abc = "kj";
// Helper function to print the first bytes a char pointer points to
void printBytes(const char *const caption, const char *const ptr)
{
int i=0;
printf("%s: {", caption);
for( i=0; i<sizeof(char *)-1; ++i)
{
printf("0x%x,", ptr[i]);
}
printf( "0x%x ...}\n", ptr[sizeof(char *)-1] );
}
// What exactly does this function do?
void fn(char**s) {
printf("Inside fn: Argument value is %p\n", s);
printBytes("Inside fn: Bytes at address above are", (char *)s);
// This throws. *s is not a valid address.
// printf("contents: ->%s<-\n", *s);
*s = abc;
printf("Inside fn: Bytes at address above after assignment\n");
printBytes(" (should be address of \"kj\")", (char *)s);
// Now *s holds a valid address (that of "kj").
printf("Inside fn: Printing *s as string (should be kj): ->%s<-\n", *s);
}
int main() {
char str[256];
printf("size of ptr: %zu\n", sizeof(void *));
strcpy(str, "AAAAAAAA"); // 9 defined bytes
printf("addr of \"kj\": %p\n", abc);
printf("str addr: %p (%p)\n", &str, str);
printBytes("str contents before fn", str);
printf("------------------------------\n");
// Paramter type does not match! Illegal code
// (6.5.16.1 of the latest public draft; incompatible
// types for assignment).
fn(&str);
printf("------------------------------\n");
printBytes("str contents after fn (i.e. abc -- note byte order!): ", str);
printf("str addr after fn -- still the same! --: %p (%p)\n", &str, str);
return 0;
}
What you have here is simply Undefined Behaviour.
The parameter to the function is declared as pointer-to-pointer-to-char. The argument passed to it is pointer-to-array-of-256-char. The standard permits conversions between one pointer and another but since the object that s points to is not a pointer-to-char, dereferencing the pointer is Undefined Behaviour.
n1570 S6.5.3.2/4:
If an invalid value has been assigned to the pointer, the behavior of the unary * operator is
undefined.
It is futile to speculate how Undefined Behaviour will play out on different implementations. It's just plain wrong.
Just to be clear, the UB is in this line:
*s=abc;
The pointer s does not point to an object of the correct type (char*), so the use of * is UB.

Dynamic allocation and pointers

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.

Get address of a string-constant in C

I would like to get the address of an string-constant in C.
char * const MYCONST = "StringString";
As far as I know consts are "saved" in the Text/Code Segment of the memory.
When I try to get the address of the first element in MYCONSt:
printf("%p\n",&(MYCONST));
As result I get 0x7fff15342e28, which is in the stack and not in the Text/Code segement.
Can anybody please help me get the address of a string-constant in C?
//edit
I can't find the correct answer so far: When I write
char * const MYCONST1 = "StringString";
printf("Address of MYCONST1: %p\n",MYCONST1);
char * const MYCONST2 = "StringString";
printf("Address of MYCONST2: %p\n",(void*)MYCONST2);
this is the output:
Address of MYCONST1: 0x400b91
Address of MYCONST2: 0x400b91
But they should have different addresses, because the are different constants.
Can anybody explain me while the result has a length of seven and not 0x7fffa5dd398c like a locale variable.
Thanks!
Since MYCONST is already a pointer, you do not need an ampersand. All you need is a cast to void* for the %p:
printf("%p\n",(void*)MYCONST);
With an ampersand, you print the address of the MYCONST local variable (you need a void* cast there as well, otherwise the address may print incorrectly), which is indeed located on the stack.
printf("%p\n",(void *) &MYCONST);
prints the address of the MYCONST pointer variable.
printf("%p\n", (void *) MYCONST);
prints the value of the MYCONST pointer variable.
Q: //edit I can't find the correct answer so far: When I write
char * const MYCONST1 = "StringString";
printf("Address of MYCONST1: %p\n",MYCONST1);
char * const MYCONST2 = "StringString";
printf("Address of MYCONST2: %p\n",(void*)MYCONST2);
this is the output:
Address of MYCONST1: 0x400b91
Address of MYCONST2: 0x400b91
But they should have different addresses, because the are different constants.
A: Since both the pointers point to same string literal. Compiler optimizes and let them share the same data and hence same address. Try compiling your code with
gcc program_name.c -O
and see. You will see the addresses different.
Relative: Addresses of two pointers are same
Address of the first character of a C string is in the variable of the string itself, i.e. MYCONST in your case.
char * const MYCONST = "StringString";
initializes a pointer MYCONST, making it point to the memory where this string literal is stored.
To print an address of this string, use the pointer's value:
printf("%p\n", (void*) MYCONST);
instead of
printf("%p\n", (void*) &MYCONST);
which prints the address of pointer itself.
printf("%p\n",(void*)MYCONST);
Will print the address of the first element of string MYCONST points to.
The reason I didn't put & before MYCONST is because MYCONST is already a pointer.
If you need to print the address of Pointer, then you need to do like &MYCONST.

Can pointers behave as variable?

I have a confusion related to this program.
#include <stdio.h>
int main(void)
{
int value = 10;
char ch = 'A';
int* ptrValue = &value;
char* ptrCh = &ch;
int* ptrValue1 = value;
char* ptrCh1 = ch;
printf("Value of ptrValue = %d and value of ptrValue1 = %d\n", *ptrValue, ptrValue1);
printf("Value of ptrCh = %c and value of ptrCh1 = %c\n", *ptrCh, *ptrCh1);
}
I get two warnings while compiling this program
unipro#ubuguest:/SoftDev/ADSD/Module
1/Unit 1/Rd/C/System$ cc
charPointers.c -o charPointers
charPointers.c: In function
‘main’: charPointers.c:11:
warning: initialization makes pointer
from integer without a cast
charPointers.c:12: warning:
initialization makes pointer from
integer without a cast
And I know what they mean.
While running the program I get the following error.
unipro#ubuguest:/SoftDev/ADSD/Module
1/Unit 1/Rd/C/System$
./charPointers Value of ptrValue
= 10 and value of ptrValue1 = 10 Segmentation fault
I know I am getting the error at second printf method.
So my question is if I store a value in pointer, why can't we de-reference it? Does it behave like a variable?
Thanks.
With the assignment
char* ptrCh1 = ch;
you will set the address to 0x41, not the value. The program will later try to de-reference 0x41 (ie. fetch the data at adress 0x41), which is an illegal address. Hence, the segmentation fault
A pointer store the address of something (or NULL). Thus an int* can store the address of an int. You get the address of something with the unary & operator.
So, what does it mean to store 10 in an int pointer ? Well, 10 is not the address of an int, so thus you get the "initialization makes pointer from integer without a cast" warning, and since you are storing something else than the address of an int in an int* and try to dereference it, you get undefined behavior.
What's likely occuring in your case is 10 gets interpreted as a memory address, and when you dereference a pointer it goes out to fetch whatever is at that address (memory address 10 in your case). There's likely nothing there, that memory area is not mapped, and you segfault.
You can dereference it, but the chances that you get a valid chunk of memory are pretty slim. Valid here means, that your process has access rights to that spot.
The OS will prevent you from modifying memory that does not belong to your process. It responds to that kind of invalid memory access with a segmentation fault "exception".
A pointer points to a memory location (in which you can then store some value). Here
int* ptrValue1 = value;
char* ptrCh1 = ch;
you assign a pointer to the value of a variable (not to its address), so the pointer most likely points to an invalid memory location, thus the segfault.
Note that in many architectures, valid memory locations start at a high offset, so a small integer value like 10 or (the ASCII value of) 'A' can never point to a valid memory location. Such low memory locations are typically reserved/used by the OS itself (thus they are protected from modification - if you try, you get a segfault). The same happens usually if you try to directly access memory used by another process.
It's because of *ptrCh1 in the last line, you are trying to dereference it. Remove the * to make it work (not that it makes much sense, though).
Sure that it must segfault. Your are storing whatever value in a pointer (and as you say the compiler warned you) and then you dereference it, regardless where this points to.
What else do you expect?

Resources