It cannot work (even theoretically), because arrays are not pointers:
int arr[10]:Amount of memory used is
sizeof(int)*10bytesThe values of
arrand&arrare necessarily identicalarrpoints 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)*10bytesThe values of
ptrand&ptrare not necessarily identical (in fact, they are mostly different)ptrcan be set to point to both valid and invalid memory addresses, as many times as you will
It cannot work (even theoretically), because arrays are not pointers:
int arr[10]:Amount of memory used is
sizeof(int)*10bytesThe values of
arrand&arrare necessarily identicalarrpoints 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)*10bytesThe values of
ptrand&ptrare not necessarily identical (in fact, they are mostly different)ptrcan be set to point to both valid and invalid memory addresses, as many times as you will
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.
#include<stdio.h>
void print(int *,int);
void main(void)
{
int a[5]={1,2,3,4,5};
//a=a+1; Not VALID (Cannot change base address of array)
print(a,5);
}
void print(int *b,int s)
{
for(int i=0;i<s;i++)
{
printf("%d ",*(b+i)); // b=b+1; is VALID here
}
}why afterall both 'b' and 'a' point to memory address of array
Changing the base address of an array !!
How to change array's variables by address in C? - Stack Overflow
Changing array inside function in C - Stack Overflow
c - Why cannot we change the base address of an array - Stack Overflow
First, recognize that you are passing addresses instead of integer values to printf_s. Take a look at the warning messages issued by the compiler. In particular, note the types of the arguments that the compiler is warning about. To determine the addresses passed to the function, the compiler is doing address arithmetic based on the type of the address. In calculating the address of &arr+1 the compiler starts by taking the address of the array. The compiler looks at the type of the argument and determines that size of the int (*)[5] type is 20. So it adds 20 to the starting address of the array.
Look at the difference in the warning messages and the result of using the following -
printf_s("%u %u\n", arr + 1, (int*) &arr + 1);
Your assumption that arr and &arr are the same is incorrect. While they happen to point to the same location in memory, they have completely different types.
In most contexts, an expression with type array of T is automatically converted to pointer to first array element. So the expression arr is treated as if you had coded &arr[0].
An exception to this conversion is when the expression is the operand of the & operator. In this case, no conversion is performed.
Pointer arithmetic is always performed with an implicit scaling based on the size of the object type pointed to. On your system, an int is 4 bytes. So arr+1 points to a location just past the end of arr[0] which is four bytes away. &arr+1 points to a location just past the end of arr which is 20 bytes away.
Also note that for the call to printf to be well defined, you should cast the values to void* and use %p as the format. While it often will work as you coded it, you should use the correct method to avoid problems when it doesn't,
In c you can't pass a variable by reference, the array variable that you assign inside the function contains initially the same address as the passed pointer, but it's a copy of it so modifying it will not alter the passed pointer.
You need to pass the address of the pointer in order to be able to alter it, like this
// Change the pointer of the array
void change(int **array, int length)
{
*array = malloc(length * sizeof(int));
if (*array == NULL)
return;
for (int i = 0 ; i < length ; i++)
(*array)[i] = 1;
}
Then in main() you cannot assign to an array, doing so through this kind of function is surely undefined behavior. The array defined in main() is allocated on the stack and you cannot assign anything to an array since they are non-writeable lvalues so you cannot make it point to a heap memory location obtained with malloc(), you need to pass a pointer like this
int *array;
change(&array, length);
free(array);
If you want the function to replace the previous array, it will have to free() the malloc()ed data (note that passing NULL to free() is well defined), so
// Change the pointer of the array
void change(int **array, int length)
{
free(*array);
*array = malloc(length * sizeof(int));
if (*array == NULL)
return;
for (int i = 0 ; i < length ; i++)
(*array)[i] = 1;
}
then in main()
int *array;
array = NULL;
change(&array, length);
change(&array, length);
change(&array, length);
change(&array, length);
free(array);
will do what you apparently want.
Ok, i will make the answer short.
- Arrays are always passed by reference in C
change(array, length); In this line, it means reference to the first element of the array variable is passed to the function.
Now the function needs a pointer to catch the reference, it can be a pointer or it can be an array. Note that the pointer or the array is local to the function.
You received it in a pointer named array. Which is definitely a pointer but it is not the same as array in main function. It is local to the change function.
You declared a new array dynamically, and assigned a pointer named new with it. And all the changes you did were to new pointer.
Everything is ok till now.
- Now you assigned the new pointer to the array pointer which is local to the change function.
This is the real issue. As even though the array is in heap section, and it will remain in the memory, but the *array and *new are local pointer variables.
Also array pointer in change function is different from array pointer in main function.
The solution to this problem is Manipulate the data of array pointer directly.
void change(int *array,int length) { int i; for(i = 0 ; i < length ; i++) array[i] = 1; }
In this way you are directly overwriting values of array in main function. Everything else is correct.
Summerization: array pointer in change function is local to change function. array in main function is local to main function. Making change function's local array pointer point to array in heap section won't change data in actual array. You changed pointer's position, Not the array's data.
arr is not a pointer, it's an array. When you use the word arr the compiler may convert it to a pointer for you - it does &arr[0] automatically, and gets the address of the first element, which is a pointer value, not a pointer variable. And you can't change values. You can't do (&some_variable)++;, you can't do 5++;, and you can't do (&arr[0])++; which is what arr++; would mean.
Arrays are not pointers.
Consider the following demonstrative program.
#include <stdio.h>
int main(void)
{
int arr[3] = { 1, 2, 3 };
int *p = arr;
printf( "sizeof( arr ) = %zu\n", sizeof( arr ) );
printf( "sizeof( p ) = %zu\n", sizeof( p ) );
return 0;
}
Its output might look like
sizeof( arr ) = 12
sizeof( p ) = 8
Arrays are non-modifiable lvalues. That means that you for example can not assign one array to another or apply an increment operator.
On the other hand, arrays used in expressions are implicitly converted (with rare exceptions) to pointers to their first elements.
From the C Standard (6.3.2.1 Lvalues, arrays, and function designators)
3 Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type โโarray of typeโโ is converted to an expression with type โโpointer to typeโโ that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.
So for example in this declaration
int *p = arr;
the array arr used as an initializer expression is implicitly converted to pointer to its first element that has the type int *.
To set the pointer p to point to the second element of the array arr you could use the pointer arithmetic the following way
int *p = arr + 1;
Because the array name decays into pointer to first element when its assigned or passed (assigned to a variable of first element's address type).
p = c; // & is not needed, and not defined behavior
printf("%p\n", (void *)&p);
Gives you the address
there are different area in memory. when you decalre a varaible it will declare in HEAP are . ROM are where the containt of varible after declare ,cant change. in your question char [], a array means varible it will go in HEAP.so 65432 or something. 2. char *p="name",is a string constant .the space for "name" will be declared in ROM area.so 772.you cant change "name" to "nass" .it may be or may not be. LAST.space for each area given by virtual memory system . ROM .LESS space --less bit addr HEAP- LARGE SPACE so---large bit for addr(generally 4 byte in window 7).
I have a char ** array that has 3 pointers
No, you don't. You have an array with three values. The values happen to be pointers. An array doesn't have pointers.
Suppose you allocate memory for this array (of pointers to char):
char **array = malloc( 3 * sizeof(char*)); // 3 values in the array
and then you allocate memory for each string:
array[0] = malloc(4 * sizeof(char) ); // 3 + 1 null terminator
array[1] = malloc(4 * sizeof(char) );
array[2] = 0;
finally you set the values for the strings themselves:
strcpy( array[0], "abc" );
strcpy( array[1], "def" );
Now you want to make a copy. A deep copy actually, because you not only allocate memory for a new array (of pointers to char) but you allocate memory for new strings as well. You do exactly the same allocation:
char **array2 = malloc( 3 * sizeof(char*));
array2[0] = malloc(4 * sizeof(char) );
array2[1] = malloc(4 * sizeof(char) );
array2[2] = 0;
Now you copy the actual strings:
strcpy( array2[0], array[0] );
strcpy( array2[1], array[1] );
If your code differs from the one above, edit your question with more details.
The tricky part is making array[0] hold the address which is in array2[0] (same for array[1] and array2[1]). The problem comes from the fact that memory you allocate via malloc needs to be freed via free.
So you can't just do
array[0] = array2[0];
Because you've lost all references to the first string you allocated. That memory is leaked.
Instead do this:
free(array[0]);
array[0] = array2[0];
This frees the memory used for the first string and copies the address of the copy.
Now you have the same pointer (value) in two variables. This is also tricky because (when you no longer need it) you still need to free the memory allocated for the copy:
free(array2[0])
The tricky part is that array[0] now holds a pointer to freed memory, which can't be used. Using it will lead to bugs.
It would probably be a good idea not to have multiple variables (in the same scope) that hold the same pointer to allocated memory. That may make it difficult to reason about the validity of the pointer.
char ** array is a pointer of pointers.
In this case, it gets assigned an array of char pointers, each of which contains the address of the first char of your eventual cstrings.
As such, you can just use the equal sign, as you would with an other regular pointer:
array[0] = (char*)0x7ffffffc;
array[1] = (char*)0x80033d;
I am dealing with a block of memory. I get the address of the block, and I store two 1 byte variables, and then a 2x8x8 1 byte array right after. I use pointers to access the variables easily.
However, when I get the addresses of the variables I notice something weird. The individual variables are 1 address from each other as expected. However, the array seems to be located 7 addresses from the last variable instead of 1 address like I expected. What is going wrong?
volatile unsigned int* address = get_address();
volatile uint8_t* var1 = (volatile uint8_t*) (address);
volatile uint8_t* var2 = (volatile uint8_t*) (address+1);
volatile uint8_t (*array1)[2][8][8] = (volatile uint8_t*) (address+2);
volatile uint8_t (*array2)[2][8][8] = (volatile uint8_t*) (address+3+2*8*8);
printf("var 1 address: %u\n",var1); // var 1 address: 3067375616
printf("var 2 address: %u\n",var2); // var 2 address: 3067375617
printf("array 1 address: %u\n",&(*array1)[0][0][0]); // array 1 address: 3067375624
printf("array 2 address: %u\n",&(*array2)[0][0][0]); // array 2 address: 3067376140Edit: I figured it out! I believe the problem was the order I was casting. To simplify things, I just changed the type of address to uint8_t* and did away with casting all together