Variable is purged when print statement is called [duplicate] - c

below program does not run as we are returning local int value.
#include<stdio.h>
int *fun1()
{
int i = 10;
return &i; // local i hence will not get printed in main
}
main()
{
int *x = fun1();
printf("%d", *x);
}
However, at the same time below program runs, even though we are returning local string base address. Why the concept of local char* does not apply here?
char *fun()
{
char *p = "ram";
return p; //char* is local, even though in main it gets printed. why?
}
int main()
{
char *x = fun();
printf("%s", x);
return 0;
}

char *fun()
{
char *p = "ram";
return p; //char* is local, even though in main it gets printed. why?
}
When you write code like this, "ram" does not get placed on the stack the same way that int i = 10 does - it gets placed in the .rodata (read only data) section of the executable. What gets placed on the stack is a pointer to this location in memory.
Imagine if "ram" wasn't three characters, but a million characters - if the string itself were to be pushed onto the stack, a million bytes would have to be pushed to the stack every time the function was called! Even though the string is constant.
Since the location of the string in memory is constant, it is valid to return a pointer to that location.

In this function
int *fun1()
{
int i = 10;
return &i; // local i hence will not get printed in main
}
the block scope variable i has automatic storage duration. It means that after exiting the function the variable will not be alive and the returned pointer to the variable will be invalid.
In this function
char *fun()
{
char *p = "ram";
return p; //char* is local, even though in main it gets printed. why?
}
the string literal "ram" having the type char[4] has static storage duration. It means that it is will be alive after exiting the function and the returned pointer to the literal will be valid.
From the C Standard (6.4.5 String literals)
6 In translation phase 7, a byte or code of value zero is appended to
each multibyte character sequence that results from a string literal
or literals.78) The multibyte character sequence is then used to
initialize an array of static storage duration and length just
sufficient to contain the sequence.
Pay attention to that the function returns a copy of the pointer p but the pointed object (the string literal) has static storage duration. So the returned pointer has a valid value.
You can achieve the same effect in the first function by declaring the variable i as having static storage duration. For example
int *fun1()
{
static int i = 10;
return &i; // local i hence will not get printed in main
}
As for your question written by you as an answer
And why below does not work? when i changed from char *p = "ram" to
char p[]="ram" ?
char *fun()
{
char p[] = "ram";
return p;
}
int main()
{
char *x = fun();
printf("%s", x);
return 0;
}
then the array p is a local array with automatic storage duration of the function. Its elements are initialized by elements of the string literal "ram". But this does change the array storage duration. In fact this declaration of the array is similar to
char p[] = { 'r', 'a', 'm', '\0' };
So this return statement
return 0;
returns a pointer to the first element of the array that (array) will not be alive after exiting the function. So the returned pointer will be invalid.

In the code
char *fun()
{
char *p = "ram";
return p; //char* is local, even though in main it gets printed. why?
}
The variable p is local to the function, and its lifetime ends with the function. However, you are returning p's value, not its address, so that doesn't really matter here.
p's value is the address of the string literal "ram". String literals are stored in such a way that they are available over the lifetime of the entire program, from startup to termination - the literal "ram" does not cease to exist when fun exits, so its address stays valid.
And why below does not work? when i changed from char *p = "ram" to char p[]="ram" ?
Now you've changed how and where the string gets stored. Instead of p being a pointer that stores the address of the string literal, it is now an array that stores the contents of the string itself. The lifetime of the string is now the same as the lifetime of the function, so once the function exits, the array that stored that string no longer exists and the return value is not valid.
I took your code and added a utility1 to display the address and contents of various items in memory. First we start with the first version where p is a pointer:
#include <stdio.h>
#include "dumper.h"
char *fun( void )
{
char *p = "ram";
char *names[] = { "p", "\"ram\"" };
void *addrs[] = { &p, "ram" };
size_t sizes[] = { sizeof p, sizeof "ram" };
puts( "In fun: ");
dumper( names, addrs, sizes, 2, stdout );
return p;
}
int main( void )
{
char *x;
char *names[] = { "x", "\"ram\"" };
void *addrs[] = { &x, "ram" };
size_t sizes[] = { sizeof x, sizeof "ram" };
puts( "Before call to fun:" );
dumper( names, addrs, sizes, 2, stdout );
x = fun();
puts( "After call to fun:" );
dumper( names, addrs, sizes, 2, stdout );
return 0;
}
And here's the output:
Before call to fun:
Item Address 00 01 02 03
---- ------- -- -- -- --
x 0x7ffee2451a40 a0 1a 45 e2 ..E.
0x7ffee2451a44 fe 7f 00 00 ....
"ram" 0x10d7aef04 72 61 6d 00 ram.
In fun:
Item Address 00 01 02 03
---- ------- -- -- -- --
p 0x7ffee24519b8 04 ef 7a 0d ..z.
0x7ffee24519bc 01 00 00 00 ....
"ram" 0x10d7aef04 72 61 6d 00 ram.
After call to fun:
Item Address 00 01 02 03
---- ------- -- -- -- --
x 0x7ffee2451a40 04 ef 7a 0d ..z.
0x7ffee2451a44 01 00 00 00 ....
"ram" 0x10d7aef04 72 61 6d 00 ram.
First, notice that the string literal "ram" has the same address in both fun and main. Again, string literals are allocated such that they are available over the lifetime of the program. You'll notice its address is much lower than the other items, indicating it's in a very different region of memory.
Again, notice that p only stores the address of the string, not its contents. So even though p ceases to exist, its value continues to be valid.
Now, we change that code so that p is an array, not a pointer:
#include <stdio.h>
#include "dumper.h"
char *fun( void )
{
char p[] = "ram";
char *names[] = { "p", "\"ram\"" };
void *addrs[] = { &p, "ram" };
size_t sizes[] = { sizeof p, sizeof "ram" };
puts( "In fun: ");
dumper( names, addrs, sizes, 2, stdout );
return p;
}
int main( void )
{
char *x;
char *names[] = { "x", "\"ram\"" };
void *addrs[] = { &x, "ram" };
size_t sizes[] = { sizeof x, sizeof "ram" };
puts( "Before call to fun:" );
dumper( names, addrs, sizes, 2, stdout );
x = fun();
puts( "After call to fun:" );
dumper( names, addrs, sizes, 2, stdout );
return 0;
}
Now our output looks like this:
Before call to fun:
Item Address 00 01 02 03
---- ------- -- -- -- --
x 0x7ffee059ea40 98 ea 59 e0 ..Y.
0x7ffee059ea44 fe 7f 00 00 ....
"ram" 0x10f661efc 72 61 6d 00 ram.
In fun:
Item Address 00 01 02 03
---- ------- -- -- -- --
p 0x7ffee059e9bc 72 61 6d 00 ram.
"ram" 0x10f661efc 72 61 6d 00 ram.
After call to fun:
Item Address 00 01 02 03
---- ------- -- -- -- --
x 0x7ffee059ea40 bc e9 59 e0 ..Y.
0x7ffee059ea44 fe 7f 00 00 ....
"ram" 0x10f661efc 72 61 6d 00 ram.
Instead of storing the address of the string literal, p now stores the contents of the string itself. Once fun exits, p (and by extension the string it contains) ceases to exist.
Available here

Related

returning local variable address vs local string address in C

below program does not run as we are returning local int value.
#include<stdio.h>
int *fun1()
{
int i = 10;
return &i; // local i hence will not get printed in main
}
main()
{
int *x = fun1();
printf("%d", *x);
}
However, at the same time below program runs, even though we are returning local string base address. Why the concept of local char* does not apply here?
char *fun()
{
char *p = "ram";
return p; //char* is local, even though in main it gets printed. why?
}
int main()
{
char *x = fun();
printf("%s", x);
return 0;
}
char *fun()
{
char *p = "ram";
return p; //char* is local, even though in main it gets printed. why?
}
When you write code like this, "ram" does not get placed on the stack the same way that int i = 10 does - it gets placed in the .rodata (read only data) section of the executable. What gets placed on the stack is a pointer to this location in memory.
Imagine if "ram" wasn't three characters, but a million characters - if the string itself were to be pushed onto the stack, a million bytes would have to be pushed to the stack every time the function was called! Even though the string is constant.
Since the location of the string in memory is constant, it is valid to return a pointer to that location.
In this function
int *fun1()
{
int i = 10;
return &i; // local i hence will not get printed in main
}
the block scope variable i has automatic storage duration. It means that after exiting the function the variable will not be alive and the returned pointer to the variable will be invalid.
In this function
char *fun()
{
char *p = "ram";
return p; //char* is local, even though in main it gets printed. why?
}
the string literal "ram" having the type char[4] has static storage duration. It means that it is will be alive after exiting the function and the returned pointer to the literal will be valid.
From the C Standard (6.4.5 String literals)
6 In translation phase 7, a byte or code of value zero is appended to
each multibyte character sequence that results from a string literal
or literals.78) The multibyte character sequence is then used to
initialize an array of static storage duration and length just
sufficient to contain the sequence.
Pay attention to that the function returns a copy of the pointer p but the pointed object (the string literal) has static storage duration. So the returned pointer has a valid value.
You can achieve the same effect in the first function by declaring the variable i as having static storage duration. For example
int *fun1()
{
static int i = 10;
return &i; // local i hence will not get printed in main
}
As for your question written by you as an answer
And why below does not work? when i changed from char *p = "ram" to
char p[]="ram" ?
char *fun()
{
char p[] = "ram";
return p;
}
int main()
{
char *x = fun();
printf("%s", x);
return 0;
}
then the array p is a local array with automatic storage duration of the function. Its elements are initialized by elements of the string literal "ram". But this does change the array storage duration. In fact this declaration of the array is similar to
char p[] = { 'r', 'a', 'm', '\0' };
So this return statement
return 0;
returns a pointer to the first element of the array that (array) will not be alive after exiting the function. So the returned pointer will be invalid.
In the code
char *fun()
{
char *p = "ram";
return p; //char* is local, even though in main it gets printed. why?
}
The variable p is local to the function, and its lifetime ends with the function. However, you are returning p's value, not its address, so that doesn't really matter here.
p's value is the address of the string literal "ram". String literals are stored in such a way that they are available over the lifetime of the entire program, from startup to termination - the literal "ram" does not cease to exist when fun exits, so its address stays valid.
And why below does not work? when i changed from char *p = "ram" to char p[]="ram" ?
Now you've changed how and where the string gets stored. Instead of p being a pointer that stores the address of the string literal, it is now an array that stores the contents of the string itself. The lifetime of the string is now the same as the lifetime of the function, so once the function exits, the array that stored that string no longer exists and the return value is not valid.
I took your code and added a utility1 to display the address and contents of various items in memory. First we start with the first version where p is a pointer:
#include <stdio.h>
#include "dumper.h"
char *fun( void )
{
char *p = "ram";
char *names[] = { "p", "\"ram\"" };
void *addrs[] = { &p, "ram" };
size_t sizes[] = { sizeof p, sizeof "ram" };
puts( "In fun: ");
dumper( names, addrs, sizes, 2, stdout );
return p;
}
int main( void )
{
char *x;
char *names[] = { "x", "\"ram\"" };
void *addrs[] = { &x, "ram" };
size_t sizes[] = { sizeof x, sizeof "ram" };
puts( "Before call to fun:" );
dumper( names, addrs, sizes, 2, stdout );
x = fun();
puts( "After call to fun:" );
dumper( names, addrs, sizes, 2, stdout );
return 0;
}
And here's the output:
Before call to fun:
Item Address 00 01 02 03
---- ------- -- -- -- --
x 0x7ffee2451a40 a0 1a 45 e2 ..E.
0x7ffee2451a44 fe 7f 00 00 ....
"ram" 0x10d7aef04 72 61 6d 00 ram.
In fun:
Item Address 00 01 02 03
---- ------- -- -- -- --
p 0x7ffee24519b8 04 ef 7a 0d ..z.
0x7ffee24519bc 01 00 00 00 ....
"ram" 0x10d7aef04 72 61 6d 00 ram.
After call to fun:
Item Address 00 01 02 03
---- ------- -- -- -- --
x 0x7ffee2451a40 04 ef 7a 0d ..z.
0x7ffee2451a44 01 00 00 00 ....
"ram" 0x10d7aef04 72 61 6d 00 ram.
First, notice that the string literal "ram" has the same address in both fun and main. Again, string literals are allocated such that they are available over the lifetime of the program. You'll notice its address is much lower than the other items, indicating it's in a very different region of memory.
Again, notice that p only stores the address of the string, not its contents. So even though p ceases to exist, its value continues to be valid.
Now, we change that code so that p is an array, not a pointer:
#include <stdio.h>
#include "dumper.h"
char *fun( void )
{
char p[] = "ram";
char *names[] = { "p", "\"ram\"" };
void *addrs[] = { &p, "ram" };
size_t sizes[] = { sizeof p, sizeof "ram" };
puts( "In fun: ");
dumper( names, addrs, sizes, 2, stdout );
return p;
}
int main( void )
{
char *x;
char *names[] = { "x", "\"ram\"" };
void *addrs[] = { &x, "ram" };
size_t sizes[] = { sizeof x, sizeof "ram" };
puts( "Before call to fun:" );
dumper( names, addrs, sizes, 2, stdout );
x = fun();
puts( "After call to fun:" );
dumper( names, addrs, sizes, 2, stdout );
return 0;
}
Now our output looks like this:
Before call to fun:
Item Address 00 01 02 03
---- ------- -- -- -- --
x 0x7ffee059ea40 98 ea 59 e0 ..Y.
0x7ffee059ea44 fe 7f 00 00 ....
"ram" 0x10f661efc 72 61 6d 00 ram.
In fun:
Item Address 00 01 02 03
---- ------- -- -- -- --
p 0x7ffee059e9bc 72 61 6d 00 ram.
"ram" 0x10f661efc 72 61 6d 00 ram.
After call to fun:
Item Address 00 01 02 03
---- ------- -- -- -- --
x 0x7ffee059ea40 bc e9 59 e0 ..Y.
0x7ffee059ea44 fe 7f 00 00 ....
"ram" 0x10f661efc 72 61 6d 00 ram.
Instead of storing the address of the string literal, p now stores the contents of the string itself. Once fun exits, p (and by extension the string it contains) ceases to exist.
Available here

C string dereference and then re-reference acting strangely?

I have the following bit of code:
#include <stdio.h>
int main(){
char *p = "abc";
char c = *p;
printf(&c);
return 0;
}
Running, I get
[OP#localhost test]$ gcc ptr.c
[OP#localhost test]$ ./a.out
a%QV[OP#localhost test]$
I was expecting it to just print "abc". Why does this happen?
char c = *p; this does a hard copy of the first letter in the string "abc", nothing else.
Therefore you end up lying to printf and tell it that at the address of the single character c, it will find a whole, valid format string.
But it will only find the character a which is not a string at all, since there is no null terminator anywhere. So anything can happen, including a program crash or the program printing garbage.
The format string is expected to be a NUL-terminated sequence of characters.
printf(p) works because
*(p+0) is 61
*(p+1) is 62
*(p+2) is 63
*(p+3) is 0
printf(&c) doesn't work because
*(&c+0) is 61
*(&c+1) is {Undefined behaviour to access}
Solution 1:
char *p = "abc";
char c = *p;
printf("%c". c); // a
Solution 2:
char *p = "abc";
char *p2 = *p; // Copies the pointer
printf(p2); // abc
Solution 3:
char *p = "abc";
char *p2 = strdup(p); // Copies the string (e.g. so you could modify it)
printf(p2); // abc
free(p2);
Tip: Unless you can guarantee a lack of %, printf(p) is usually wrong. Use printf("%s", p).

Why is char[] on the stack but char * on the heap?

I'm very confused about what's happening. I always thought char * and char [] were interchangable, but after looking at the memory addresses it seems char * allocates space in the heap, whereas char [] is allocating memory on the stack.
char stack[] = "hello";
char *heap = "hello";
char *heap_string_malloc = malloc(5);
heap_string_malloc = "hello";
printf("Address of stack[0]: %p\n", stack);
printf("Address of heap[0]: %p\n", heap);
printf("Address of heap_string_malloc[0]: %p\n", heap_string_malloc);
Outputs the following:
Address of stack[0]: 0x7fff8b0b85b0
Address of heap[0]: 0x400760
Address of heap_string_malloc[0]: 0x400760
Does this mean that char * is dynamically allocated?
Further to my confusion, how come malloc is allocating the same memory address as what char *heap has already allocated? I'm not running any optimisation (simply gcc file.c).
Arrays are not pointers. What your program is doing, line by line, is
// Allocate 6 bytes in the stack and store "hello" in them
char stack[] = "hello";
// Allocate pointer on the stack and point it to a static, read-only buffer
// containing "hello"
char *heap = "hello";
// Malloc 5 bytes (which isn't enough to hold "hello" due to the NUL byte)
char *heap_string_malloc = malloc(5);
// Reset heap_string_malloc to point to a static buffer; memory leak!
heap_string_malloc = "hello";
The reason you're seeing the same pointer twice is because the compiler optimized away the second static buffer containing "hello".
When you do e.g.
char *heap = "hello";
the pointer heap actually does not point to the heap, it points to static data loaded together with the rest of program by the operating system loader. In fact, to be correct it should be
const char *heap = "hello";
as heap is pointing to a constant and read-only piece of memory.
Also, while arrays decays to (and can be used as) pointers, and pointers can be used with array syntax, they are not the same. The biggest difference being that for an array you can use e.g. sizeof to get the size in bytes of the actual array, while it's not possible for pointers.
And as a third thing, when you're doing
char *heap_string_malloc = malloc(5);
heap_string_malloc = "hello";
you have a memory leak, as you first assign something to heap_string_malloc but then directly afterward reassign heap_string_malloc to point to something completely different.
As for the reason you get the same address for both heap and heap_string_malloc it's because both points to the same literal string.
String literals such as "hello" are stored in such a way that they are held over the lifetime of the program. They are often stored in a separate data segment (distinct from the stack or heap) which may be read-only.
When you write
char stack[] = "hello";
you are creating a new auto ("stack") variable of type "6-element array of char" (size is taken from the length of the string literal), and the contents of the string literal "hello" are copied to it.
When you write
char *heap = "hello";
you are creating a new auto ("stack") variable of type "pointer to char", and the address of the string literal "hello" is copied to it.
Here's how it looks on my system:
Item Address 00 01 02 03
---- ------- -- -- -- --
"hello" 0x400b70 68 65 6c 6c hell
0x400b74 6f 00 22 68 o."h
stack 0x7fffb00c7620 68 65 6c 6c hell
0x7fffb00c7624 6f 00 00 00 o...
heap 0x7fffb00c7618 70 0b 40 00 p.#.
0x7fffb00c761c 00 00 00 00 ....
*heap 0x400b70 68 65 6c 6c hell
0x400b74 6f 00 22 68 o."h
As you can see, the string literal "hello" has its own storage, starting at address 0x400b70. Both the stack ahd heap variables are created as auto ("stack") variables. stack contains a copy of the contents of the string literal, while heap contains the address of the string literal.
Now, suppose I use malloc to allocate the memory for the string and assign the result to heap:
heap = malloc( sizeof *heap * strlen( "hello" + 1 ));
strcpy( heap, "hello" );
Now my memory map looks like the following:
Item Address 00 01 02 03
---- ------- -- -- -- --
"hello" 0x400b70 68 65 6c 6c hell
0x400b74 6f 00 22 68 o."h
stack 0x7fffb00c7620 68 65 6c 6c hell
0x7fffb00c7624 6f 00 00 00 o...
heap 0x7fffb00c7618 10 10 50 00 ..P.
0x7fffb00c761c 00 00 00 00 ....
*heap 0x501010 68 65 6c 6c hell
0x501014 6f 00 00 00 o...
The heap variable now contains a different address, which points to yet another 6-byte chunk of memory containing the string "hello".
EDIT
For byteofthat, here's the code I use to generate the above map:
dumper.h:
#ifndef DUMPER_H
#define DUMPER_H
/**
* Dumps a memory map to the specified output stream
*
* Inputs:
*
* names - list of item names
* addrs - list of addresses to different items
* lengths - length of each item
* count - number of items being dumped
* stream - output destination
*
* Outputs: none
* Returns: none
*/
void dumper(char **names, void **addrs, size_t *lengths, size_t count, FILE *stream);
#endif
dumper.c:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "dumper.h"
/**
* Dumps a memory map to the specified output stream
*
* Inputs:
*
* names - list of item names
* addrs - list of addresses to different items
* lengths - length of each item
* count - number of items being dumped
* stream - output destination
*
* Outputs: none
* Returns: none
*/
void dumper(char **names, void **addrs, size_t *lengths, size_t count, FILE *stream)
{
size_t i;
int maxlen = 15;
for ( size_t j = 0; j < count; j++ )
{
if (strlen(names[j]) > maxlen && strlen(names[j]) < 50)
maxlen = strlen(names[j]);
}
fprintf(stream,"%*s%15s%5s%5s%5s%5s\n", maxlen, "Item", "Address", "00", "01",
"02", "03");
fprintf(stream,"%*s%15s%5s%5s%5s%5s\n", maxlen, "----", "-------", "--", "--",
"--", "--");
for (i = 0; i < count; i++)
{
size_t j;
char *namefield = names[i];
unsigned char *p = (unsigned char *) addrs[i];
for (j = 0; j < lengths[i]; j+=4)
{
size_t k;
fprintf(stream,"%*.*s", maxlen, maxlen, namefield);
fprintf(stream,"%15p", (void *) p);
for (k = 0; k < 4; k++)
{
fprintf(stream,"%3s%02x", " ", p[k]);
}
fprintf(stream, " ");
for ( k = 0; k < 4; k++)
{
if (isgraph(p[k]))
fprintf(stream,"%c", p[k]);
else
fprintf(stream, ".");
}
fputc('\n', stream);
namefield = " ";
p += 4;
}
fputc('\n', stream);
}
}
And an example of how to use it:
#include <stdio.h>
#include "dumper.h"
int main(void)
{
int x = 0;
double y = 3.14159;
char foo[] = "This is a test";
void *addrs[] = {&x, &y, foo, "This is a test"};
char *names[] = {"x", "y", "foo", "\"This is a test\""};
size_t lengths[] = {sizeof x, sizeof y, sizeof foo, sizeof "This is a test"};
dumper(names, addrs, lengths, 4, stdout);
return 0;
}
This creates an array on the stack, containing a copy of the static string "hello":
char stack[] = "hello";
This creates a pointer on the stack, containing the address of the static string "hello":
char *heap = "hello";
This creates a pointer on the stack, containing the address of a dynamically allocated buffer of 5 bytes:
char *heap_string_malloc = malloc(5);
But in all three cases, you put something on the stack. char* is not "on the heap". It is a pointer (on the stack) which points to something, somewhere.
"stack" is a static array of chars so it will be allocated in the stack and freed automatically once the function ends, because its size is known since its definition.
While "heap" and "heap_string_malloc" are both declared as pointers to char buffers and need to be allocated dynamicly with malloc in order to define the size of their content, that's why they will reside in the heap memory.
By doing:
char *heap = "hello";
and:
heap_string_malloc = "hello";
you are modifying the pointers them-self (with a static buffer value), not the content to which they're pointing. You should rather use memcpy to modify the memory pointed by the "heap_string_malloc" pointer with your data:
memcpy(heap_string_malloc, "hello", 5);

How to set value of unsigned char array on C

I have an unsigned char array of size 64 that i want to change value of at runtime, however all my attemps have failed miserably, what am I doing wrong?
int main() {
unsigned char buffer[64]={0xef,0xaa,0x03,0x05,0x05,0x06,0x07,0x08,......};
buffer = {0x01,0x04,0xa0,0xb0,0xde,0x00,.....}; //fails
return 0;
}
EDIT: I don't want to fill with zero's the array buffer, I want to place a new value
Another solution would be the use of almighty memcpy() and C99 compound literals:
memcpy(array, (int []){ 0x00, 0x01, 0x02 }, sizeof array);
Believe it or not, this works.
for (int i = 0; i < 64; ++i) buffer[i] = 0x00;
or in C++ (11 or later), you can use std::fill_n or std::generate_n
std::fill_n(buffer, 64, 0x00);
or
for (auto &b : buffer) b = 0x00;
From your comment I see you do not want to access elements of the array. If not, then here is another solution to your problem.
You could declare the buffer on the memory pool. Hence,
unsigned char *buffer = malloc( sizeof( unsigned char ) * 64 );
... and then if you ever wanted to replace all of the elements of the array (as you have attempted to do using the array initialization syntax), it would be done as follows:
memset( buffer, 0x00, sizeof( unsigned char ) * 64 ); // To replace buffer = { 0x00, ..., 0x00 };.
memset( buffer, 0, sizeof( unsigned char ) * 64 ); // To replace buffer = '0...0';.
Legacy:
If you wanted to use an array declared on the stack then you would need to mutate it one element at a time using the square brackets [ ]. It would be done as follows:
for ( int i = 0; i < 64; i++ ) {
buffer[ i ] = val; // where "val" is some value.
}
Use std::memset:
memset(buffer, 0, sizeof(buffer));
There's also bzero, but it's a legacy function, so it shouldn't be used in new development.
You can change the values of the element in two ways :
unsigned char buffer[64]={0xef,0xaa,0x03,0x05,0x05,0x06,0x07,0x08,......};
buffer[0] = 0;
buffer[1] = 15;
// etc ...
// C++11 for-loop range works fine to :
for ( auto &c : buffer )
c = 0;
Or after that, you can use function like : memset, std::fill_n :
memset( buffer, 0, sizeof(buffer) );
std::fill_n( buffer, 64, 0x00 );
You could use snprintf:
#include <stdio.h>
int main() {
unsigned char buffer[64]={0};
snprintf(buffer, 64, "Hello World!\x0D\x0A");
printf(buffer);
}
Output:
$ ./a.out | hexdump -C
00000000 48 65 6c 6c 6f 20 57 6f 72 6c 64 21 0d 0a |Hello World!..|
0000000e
Initialization and assignment are two different operations, despite similarity in the syntax.
int x[4] = { 1, 2, 3, 4}; // initialization
x = { 1, 2, 3, 4}; // assignment
Additionally, raw arrays in C and C++ behave strangely and in particular there's a special rule that says that they are not assignable:
int x[4];
int y[4];
y = x; // error, arrays are not assignable
So even if you create an array temporary object you cannot simply copy that into another array object using the assignment operator.
Instead, if you are set on using raw arrays, you have to set each array element individually, using memcpy, fill, etc.
A better solution is to use C++ and a type other than raw arrays which does allow assignment, such as std::array<unsigned char, 64>:
std::array<unsigned char, 64> buffer = {0xef,0xaa,0x03,0x05,0x05,0x06,0x07,0x08};
buffer = {}; // zeros out the array
The std::array template just generally behaves consistently like a normal object whereas raw arrays in C and C++ have all these very strange behaviors and special cases in the language specs. You should avoid using raw arrays.
Unfortunately C does not have any alternative to raw arrays.
Since that are some compiler issues, try a simple usage of memcpy().
#include <string.h>
int main() {
unsigned char bufferTo[ 64]={0xef,0xaa,0x03,0x05,0x05,0x06,0x07,0x08,......};
unsigned char bufferFrom[64]={0x01,0x04,0xa0,0xb0,0xde,0x00,.....};
memcpy(bufferTo, bufferFrom, 64);
return 0;
}

Understanding strings and arrays

Consider this code.
int main()
{
char *s, *t;
s = malloc(4 * sizeof(char));
strcpy(s, "foo");
t = s;
printf("%s %s\n", s, t); // Output --> foo foo
strcpy(s, "bar"); // s = "bar"
printf("%s %s\n", s, t); // Output --> bar bar
}
There are 2 strings s and t. First I set s to "foo" and then make t point to s. When I print the strings, I get foo foo.
Then, copy "bar" tos and print again, I get bar bar.
Why does value of t changes in this case? (I copied "bar" to s why did t change).
Now when I change strcpy(s, "bar") to s = "bar" -
int main()
{
char *s, *t;
s = malloc(4 * sizeof(char));
strcpy(s, "foo");
t = s;
printf("%s %s\n", s, t); // Output --> foo foo
s = "bar"
printf("%s %s\n", s, t); // Output --> bar foo
}
This code gives me foo foo and bar foo.
Why didn't it change in this case?
This is undefined behaviour, which means anything can happen:
char *s, *t;
strcpy(s, "foo");
as strcpy() is writing to a random location in memory because s is an uninitialised pointer.
(after edit that corrected undefined behaviour)
Question 1 - Why does value of t changes in this case? (I copied "bar" to s why did t change).
This is a pointer assignment:
t = s;
and results in both t and s pointing to the same memory that was malloc() and assigned to s earlier. Any change to that memory is visible via both t and s.
Question 2 - Why isn't t changing in the second case?
This assigns the address of the string literal "bar" to s:
s = "bar";
so now t and s do not point to the same memory location. t points to the memory that was earlier malloc() and assigned to s (because of the t = s; pointer assignment).
strcpy() and = are very different:
strcpy() copies characters to the memory address specified by its first argument
assignment, =, changes the address which a pointer holds
strcpy(s, "foo");
Copies foo to memory location pointed to by s
t = s;
Now, t and s both point to same location
Hence, same output
Now, you copy bar to s. Since both t and s point to same location. Hence, same output again.
Upto this line everything is same
s = "bar"
You create a string constant bar. And assign its address to s. Its a pointer it can point to any memory location. not necessarily the original one.
Now,
s points to bar and t still to the earlier location it pointed to in the beginning and hence the output
a simplistic way to understand could be as follows :-
s = malloc(4 * sizeof(char)); // this will be interpreted as follows
s = 123 ------------>| | | | | //some garbage values at these location
123 124 125 126 // some random address chosen.
strcpy(s, "foo") ; // it copies at the address provided by s i.e.
|'f'|'o'|'o'|'\0'|
123 124 125 126
t = s; this statement means t it pointing to address = 123
strcpy(s, "bar"); // this statement copies at given address it means it will override previous value . i.e
|'b'|'a'|'r'|'\0'|
123 124 125 126
now t still pointing to address 123 that is why t, s both prints bar .
s = "bar" // this will assign a new address to s which is base address of "bar" string . i.e .
|'b'|'a'|'r'|'\0'|
321 322 323 324
now s will contain address 321 while t has value 123 that is why s and t are giving different values .

Resources