I'm sure this has been asked before, but a cursory google and stack overflow search didn't turn up the answer.
#include <stdio.h>
int main() {
char a[128][1024];
strcpy(a[0], "hello");
strcpy(a[1], "foo");
strcpy(a[2], "bar");
char **b = a;
printf("%s\n", a[0]); //same as printf("%s\n", a)
printf("%s\n", a[2]+1); //print from 2nd char of 3rd string
printf("%s\n", b); //same as printf("%s\n", a), makes sense
printf("%s\n", b[0]); //segfault???
}
First off, why is the last one a segfault? I'd expect same behavior as array a. How would I access the n-th string from b in a generalized way? What are the differences in treatment between a and b?
On a similar note, the way I understand it, a[n] is syntactic sugar for *(a+n). Is this correct, both for pointers and for arrays? Yet it seems getting different behavior for a and b.
Thanks!
char **b says “At the place where b points, b[0], there is a pointer to a char. And, if I use b[1], b[2],…, those are also pointers to char.”
In contrast char a[128][1024] says “a is 128 arrays of 1024 char.” When you do this, at the place where a is, there are no pointers. There are just char. In memory, it looks like 131,072 char in a row (128•1024 = 131,072).
When you assign char **b = a, assuming the compiler allows you to, you set b to be the address of a. When you use b[0], there should be a pointer there. But there is not. There are just char there. When you pass b[0] to printf, the compiler goes to where b points, loads several bytes as if they were a pointer, and passes the resulting value to printf. Then printf crashes, because the bytes point to some bad location.
A proper definition of b would be char (*b)[1024] = a;.
This
char **b = a;
is a type mismatch as a is char[][] which used without index is a char *.
You might like to switch an all compiler warning (on gcc this is doen via -Wall).
This line
printf("%s\n", b[0]);
dereferences a pointer to a pointer to character, that is an address value. Then it tries to print the address value value as a (0-terminated) string, what most likely is going to access random memory.
Related
I m running this using rextester (online compiler). I followed a tutorial but there is something I don't understand.
I thought it would be better to write my question directly inside the code.
//gcc 5.4.0
#include <stdint.h>
#include <stdio.h>
uint8_t var1 = 17;
uint8_t var2 = 23;
uint8_t arr[] ={7,9,11};
uint64_t *ptr1;//pointer
uint64_t *ptr2;
uint64_t *ptr3;
int main(void)
{
printf("var1: %d\n", var1) ;
//connecting pointer to address
ptr1 = &var1;
printf("address of ptr1: %d\n", ptr1) ;
printf("value of ptr1: %d\n\n", *ptr1) ;
//connecting pointer to address + 1
ptr2 = &var1 +1;
printf("address of ptr2: %d\n", ptr2) ;
//assign value to pointer
*ptr2 = var2;
printf("value of ptr2: %d\n\n", *ptr2) ;
//try on array
ptr3= &arr;//no need to point element 0, or yes?
printf("address of ptr3: %d\n", ptr3) ;
printf("value of ptr3: %d\n\n", *ptr3) ;//i expect 7
return 0;
}
Any help would be very appreciate to help me understand the right behaviour of pointers in c and cpp
I made a lot of tries but i m not able to link a pointer to an array
Edit after response of mato:
Do you think this is a clean way to work with pointer and array? Or there are better solution which take care of not overwriting memory?
//gcc 5.4.0
#include <stdint.h>
#include <stdio.h>
uint16_t var = 17;
uint16_t arr[] ={3,5,7,11,13};
uint16_t *ptr;
int main(void)
{
printf("var: %d\n", var) ;
//connecting pointer to address
ptr = &var;
printf("address of ptr: %d\n", ptr) ;
printf("value of ptr: %d\n\n", *ptr) ;
//try on array
for (uint16_t n =0;n<5;n++){
ptr= &arr[n] ;
printf("item: %d value: %d ads: %d pointer: %d\n", n, arr[n], ptr, *ptr) ;
}
return 0;
}
It seems that you do understand what pointers are and you can use them with basic types.
There are two problems in your code. First is this part:
//connecting pointer to address + 1
ptr2 = &var1 + 1;
Here you assigned some address to variable ptr2. Up to this point there is nothing dangerous about that.
But then you assign a value to memory at that address
//assign value to pointer
*ptr2 = var2;
This is dangerous because you, as a developer, don't know what is stored at that address. Even if you are lucky right now, and that part of memory isn't being used for anything else, it will most likely change once your program gets longer and then you will have hard time searching for the bug.
Now arrays usually are a bit confusing, because when you create an array like this:
uint8_t arr[] = {7,9,11};
three things happen.
Your program allocates continual block of memory, that fits 3 variables of type uint8_t. The 3 variables in this context are called elements.
The elements will get the provided initial values 7, 9 and 11.
An address of first element (the one that contains value 7) will be stored in arr.
So arr is actually of type uint8_t *.
In order to get the last part do what you expect, you just need to change this one line (remove the &):
ptr3 = arr;
EDIT: BTW watch and understand this course and you will be expert on C memory manipulation. Video is a bit dated, but trust me, the guy is great.
EDIT2: I just realised the other answer is absolutely correct, you really need to match the types.
You are doing many mistakes. Up to the point, that g++ does not compile the code and explains why pretty good.
Pointer is an address. There is no "connecting pointer to address". ptr1 = &var1; means literally "store address of var1 in variable named ptr1"
You use incompatible pointer types. So as long as you dereference it (e.g. using *) you are going into undefined behaviour.
I am pretty sure you can reinterpret any type of data as char* or unsigned char*, I image this is true for equivalent types like uint8_t, i.e. single byte types.
You, however, are going the other way, you declare 1-byte data, and are pretending it's a 4 byte int. Basically you force the program to read memory out the variable bounds.
Fact, that *ptr1 and *ptr2 give result you expect is a rather lucky coincidence. Probably memory behind them was zeroed. For ptr3 it isn't because you have filled it with other element of the array (7 and 9).
I believe you also use wrong type specifier for printing. %d is for int, uint8_t should be described as hhu and uint64_t as lu. I am not 100% convinced how fatal this is, because of platform specific widths and integer promotions.
You should use matching types for your pointers and variables.
I have the following code snippet
int a = 10;
char *p = &a;
printf("%d", *p);
printf("%c", *p);
What happens in memory? What will it print and why?
char *p = &a; is a constraint violation. Your compiler must give a diagnostic message, which you shouldn't ignore.
Some compilers will say "warning" and silently transform the code to:
char *p = (char *)&a;
The effect of this is that p still points to the same memory location as a, however p has a different type. If you read or write through p then the memory locations that store the representation of a will be treated as if they stored characters. This is called aliasing.
Aliasing is permitted to char but in general, not permitted for other combinations of types.
Reading *p will retrieve the first byte of the storage of a. The actual number printed is (probably) implementation-defined; common systems would give 0 or 10.
I'm a beginner in C++, and I have problem with understanding some code.
I had an exercise to do, to write function which returns size of int, and do not use sizeof() and reinterpret_cast. Someone gave me solution, but I do not understand how it works. Can you please help me to understand it? This is the code:
int intSize() {
int intArray[10];
int * intPtr1;
int * intPtr2;
intPtr1 = &intArray[1];
intPtr2 = &intArray[2];
//Why cast int pointer to void pointer?
void* voidPtr1 = static_cast<void*>(intPtr1);
//why cast void pointer to char pointer?
char* charPtr1 = static_cast<char*>(voidPtr1);
void* voidPtr2 = static_cast<void*>(intPtr2);
char* charPtr2 = static_cast<char*>(voidPtr2);
//when I try to print 'charPtr1' there is nothing printed
//when try to print charPtr2 - charPtr1, there is correct value shown - 4, why?
return charPtr2 - charPtr1;
}
To summarize what I don't understand is, why we have to change int* to void* and then to char* to do this task? And why we have the result when we subtract charPtr2 and charPtr1, but there is nothing shown when try to print only charPtr1?
First of all, never do this in real-world code. You will blow off your leg, look like an idiot and all the cool kids will laugh at you.
That being said, here's how it works:
The basic idea is that the size of an int is equal to the offset between two elements in an int array in bytes. Ints in an array are tightly packed, so the beginning of the second int comes right after the end of the first one:
int* intPtr1 = &intArray[0];
int* intPtr2 = &intArray[1];
The problem here is that when subtracting two int pointers, you won't get the difference in bytes, but the difference in ints. So intPtr2 - intPtr1 is 1, because they are 1 int apart.
But we are in C++, so we can cast pointers to anything! So instead of using int pointers, we copy the value to char pointers, which are 1 byte in size (at least on most platforms).
char* charPtr1 = reinterpret_cast<char*>(intPtr1);
char* charPtr2 = reinterpret_cast<char*>(intPtr2);
The difference charPtr2 - charPtr1 is the size in bytes. The pointers still point to the same location as before (i.e. the start of the second and first int in the array), but the difference will now be calculated in sizes of char, not in sizes of int.
Since the exercise did not allow reinterpret_cast you will have to resort to another trick. You cannot static_cast from int* to char* directly. This is C++'s way of protecting you from doing something stupid. The trick is to cast to void* first. You can static_cast any pointer type to void* and from void* to any pointer type.
This is the important bit:
intPtr1 = &intArray[1];
intPtr2 = &intArray[2];
This creates two pointers to adjacent ints in the array. The distance between these two pointers is the size of an integer that you're trying to retrieve. However the way that pointer arithmetic works is that if you subtract these two then the compiler will return you the size in terms of ints, which will always be 1.
So what you're doing next is re-casting these as character pointers. Characters are (or de-facto are) 1 byte each, so the difference between these two pointers as character pointers will give you an answer in bytes. That's why you're casting to character pointers and subtracting.
As for via void* - this is to avoid having to use reinterpret_cast. You're not allowed to cast directly from a int* to a char* with static_cast<>, but going via void* removes this restriction since the compiler no longer knows it started with an int*. You could also just use a C-style cast instead, (char*)(intPtr1).
"do not use sizeof() and reinterpret_cast"... nothing's said about std::numeric_limits, so you could do it like that :)
#include <limits>
int intSize()
{
// digits returns non-sign bits, so add 1 and divide by 8 (bits in a byte)
return (std::numeric_limits<int>::digits+1)/8;
}
Pointer subtraction in C++ gives the number of elements between
the pointed to objects. In other words, intPtr2 - intPtr1
would return the number of int between these two pointers.
The program wants to know the number of bytes (char), so it
converts the int* to char*. Apparently, the author doesn't
want to use reinterpret_cast either. And static_cast will
not allow a direct convertion from int* to char*, so he
goes through void* (which is allowed).
Having said all that: judging from the name of the function and
how the pointers are actually initialized, a much simpler
implementation of this would be:
int
intSize()
{
return sizeof( int );
}
There is actually no need to convert to void*, other than avoiding reinterpret_cast.
Converting from a pointer-to-int to a pointer-to-char can be done in one step with a reinterpret_cast, or a C-style cast (which, by the standard, ends up doing a reinterpret_cast). You could do a C-style cast directly, but as that (by the standard) is a reinterpret_cast in that context, you'd violate the requirements. Very tricky!
However, you can convert from an int* to a char* through the void* intermediary using only static_cast. This is a small hole in the C++ type system -- you are doing a two-step reinterpret_cast without ever calling it -- because void* conversion is given special permission to be done via static_cast.
So all of the void* stuff is just to avoid the reinterpret_cast requirement, and would be silly to do in real code -- being aware you can do it might help understanding when someone did it accidentally in code (ie, your int* appears to be pointing at a string: how did that happen? Well, someone must have gone through a hole in the type system. Either a C-style cast (and hence a reinterpret_cast), or it must have round-tripped through void* via static_cast).
If we ignore that gymnastics, we now have an array of int. We take pointers to adjacent elements. In C++, arrays are packed, with the difference between adjacent elements equal to the sizeof the elements.
We then convert those pointers to pointers-to-char, because we know (by the standard) that sizeof(char)==1. We subtract these char pointers, as that tells us how many multiples-of-sizeof(char) there are between them (if we subtract int pointers, we get how many multiples-of-sizeof(int) there are between them), which ends up being the size of the int.
If we try to print charPtr1 through std::cout, std::cout assumes that our char* is a pointer-to-\0-terminated-buffer-of-char, due to C/C++ convention. The first char pointed to is \0, so std::cout prints nothing. If we wanted to print the pointer value of the char*, we'd have to cast it to something like void* (maybe via static_cast<void*>(p)).
Please read this: richly commented.
int intSize()
{
int intArray[2]; // Allocate two elements. We don't need any more than that.
/*intPtr1 and intPtr2 point to the addresses of the zeroth and first array elements*/
int* intPtr1 = &intArray[0]; // Arrays in C++ are zero based
int* intPtr2 = &intArray[1];
/*Note that intPtr2 - intPtr1 measures the distance in memory
between the array elements in units of int*/
/*What we want to do is measure that distance in units of char;
i.e. in bytes since once char is one byte*/
/*The trick is to cast from int* to char*. In c++ you need to
do this via void* if you are not allowed to use reinterpret_cast*/
void* voidPtr1 = static_cast<void*>(intPtr1);
char* charPtr1 = static_cast<char*>(voidPtr1);
void* voidPtr2 = static_cast<void*>(intPtr2);
char* charPtr2 = static_cast<char*>(voidPtr2);
/*The distance in memory will now be measure in units of char;
that's how pointer arithmetic works*/
/*Since the original array is a contiguous memory block, the
distance will be the size of each element, i.e. sizeof(int) */
return charPtr2 - charPtr1;
}
Consider the following program.
#include <stdio.h>
int main()
{
int a[10]={0};
printf("%p %p\n", a, &a);
printf("%d %d\n", *a, *(&a));
return 0;
}
a and &a are same. But *a and *(&a) are not. I am out of answers. Please help.
a[i] is the same as *(a + i). So the first element is at the same address as the array itself.
You'll find a more detailed explanation in another question here on SO: How come an array's address is equal to its value in C?
There is no "array base pointer", i.e. there no pointer variable that points to the array. The name of the array refers to the array itself. Therefore you can not take an address of a, instead, &a is handled as a special case.
When you use the name of an array in an expression, it decays into a pointer that points to the first element of the array. However, & and sizeof operators are exceptions.
ANSI C specifies that &a means the address of the array itself, and its type is "pointer to array", not "pointer to array element".
In pre-ANSI compilers, &a would cause a warning.
The address of an array is one of those things you learn early on in C. The address of the buffer is the address of its first element. In the case of
printf("%d %d\n", *a, *(&a));
*a takes the value of a.
*(&a) first take's a's address, and then deferences from that.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char szBuffer[100];
char *pBufferPtr = NULL;
int main(int argc, char *argv[])
{
pBufferPtr = szBuffer;
printf("%s %i\n %s %i\n %s %i\n",
"szBuffer's address: ", (int ) szBuffer,
"&szBuffer[0]'s address: ", (int ) &szBuffer[0],
"pBufferPtr's address: ", (int ) pBufferPtr);
printf("\n%s\n", "Program ended.");
return 0;
}
As I learned many years ago, sometimes the best thing to do with pointers is write what used to be called "stub" code, and then examine in the debugger or use "print" (printf) statements. What gets trickier is when you want to modify what a pointer points to, instead of its contents.
a and &a have the same value, but they are different types: int * and int **. You should have got a warning when you compiled you code.
Your second line will work if you add an extra * like this:
printf("%d %d\n", *a, **(&a));
This does make sense: if *a dereferences a and gives the first element of the array, and &a means take the address of a, then *(&a) takes the address of a, dereferences that, and arrives back at a once more.
#include <stdio.h>
#include <string.h>
#include <conio.h>
#include <iostream>
using namespace std;
char a[21]; // If this is put inside the function unter -> junk output
char* b="";
void unter()
{
char *new_str = "";
strcpy(a, new_str);
char str_temp[10]="";
int chnum =0, neighbor1=3, neighbor2=5, mynode=4;
sprintf(str_temp,"%d",chnum);
b = strcat(a, str_temp);
b = strcat(b, "_from");
sprintf(str_temp,"%d",mynode);
b = strcat(b, str_temp);
b = strcat(b, "to");
sprintf(str_temp,"%d",neighbor1);
b = strcat(b, str_temp);
}
int main()
{
unter();
cout << a;
cout << b;
std::cin.get();
}
This is my code in C++. I'm not sure how the character array 'a' also has the same values as 'b'. And moreover, when I declare 'a'
char a[21];
inside function unter(), I'm getting some junk value for 'b'(as output). Care to explain how?
a is a char array and b is a pointer that points to a, so when printing them, they always print the same thing. When you move the declaration for a into unter, it is destroyed when unter returns, leaving b a dnagling pointer, so you get garbage when you print it.
b = strcat(a, str_temp);
is probably what's causing your issue, since the return value from strcat() is the first parameter that was passed to it, hence why you're seeing a and b becoming equal, since b is getting set to a in that call.
strcat() returns the result of the concatenation operation, so
b = strcat(a, str_temp);
results in b pointing to the array a[]. The subsequent strcat() operations effectively do the same, so the end result is that b points to a[] as you observe. If you declare a[] inside unter() it will have local scope to that function, with the result that the global variable b will point to random/undefined memory contents after you exit the call to unter().
It's mildly worth noting that you're doing a lot of work that could be accomplished more easily with
sprintf(a, "%d_from%dto%d", chnum, mynode, neighbor1);
You can do the whole concatenation and sprintf's in a single line.
char* b="";
void unter()
{
int chnum =0, neighbor1=3, neighbor2=5, mynode=4;
char str_temp[21];
sprintf(str_temp,"%d_from%dto%d", chnum, mynode, neighbor1);
b = new char[strlen(str_temp)+1];
b = strcpy(b, str_temp);
}
Only funny thing is you must remember to delete b when you are done. The other option is using the a buffer and sprintf directly to it:
char a[21];
void unter()
{
int chnum =0, neighbor1=3, neighbor2=5, mynode=4;
char str_temp[21];
sprintf(a,"%d_from%dto%d", chnum, mynode, neighbor1);
}
When you define a inside the function, memory for the variable a is allocated on stack. This memory is destroyed when the function exits. Your pointer b is pointing to starting address of a. Now, if you try to access b outside the function, it is pointing to a memory location which is already destructed and contain garbage values. Basically, b becomes a dangling pointer.
If you declare a inside the unter() function, then it is only scoped inside that function. Attempt to print b from outside the function will print junk since it is pointing to a which is already destroyed.
This is a classic example of why you should always make sure to not to point to a local variable from a global one.
In addition to the other hints provided, you should take notice of the line
b = strcat(b, str_temp);
which seems rather inappropriate for b is merely defined as a char pointer to a single byte storage ("" defines an empty string, i.e. an array of chars with a single element containing '\0')
So when strcat appends to b, it creates a buffer overrun.
Edit:Actually I just noticed that b was assigned to point to a, (thanks to the line preceding the one mentionned) so that would then be ok, since a may have the room for this... It doesn't make sense however, to need the two variables.
Maybe what you do not understand, is that although strcat() returns a pointer, this return doesn't need to be "consumed", it is merely a convenience, for when we chain commands an such. In other words you can simply write:
strcat(a, str_temp);
Not requiring any char * b.