I would like to copy 4 bytes from unsigned int to unsigned char array. Once executed the following function get_result goes to segmentation fault :
int exec_cmd(unsigned int * apu32Var)
{
int ret = -1;
char cmd[100] = { 0 };
char resp[100] = { 0 };
sprintf(cmd, "%s %s", "/home/send_frames.sh", "read");
ret = exec_cmd_ret_result(cmd, resp);
if( apu32Var != NULL )
{
*apu32Var = (((unsigned int)resp[0]) <<24)+(((unsigned int)resp[1]) <<16)+(((unsigned int)resp[2]) <<8)+(unsigned int)resp[3];
}
return ret;
}
int get_result(unsigned char * buffer, unsigned short * size)
{
unsigned int u32Var = 0;
exec_cmd(&u32Var);
memcpy(buffer, &u32Var, sizeof(unsigned int));
*size += sizeof(unsigned int);
return 0;
}
int main(int argc, char **argv)
{
unsigned char *buf;
unsigned short *size;
get_result(buf+4, size);
return 0;
}
However, regarding to memcpy() man page it seems memcpy() are well managed. What is going wrong ?
Assuming your call to test_result actually should be calling get_result, then you have two big problems.
The first and most serious is that you pass in uninitialized local variables as arguments to the function. Uninitialized local variables have indeterminate values. For a pointer, it means it can point just about anywhere, and trying to dereference it will lead to undefined behavior. You need to actually make these pointers point somewhere valid for it to work. This goes for both variables.
The second problem is that you misunderstand how emulating pass by reference works in C. Yes the function should take a pointer, but you should not actually create a pointer variable and pass to the function. Instead you should use the address-of operator & on a non-pointer variable.
To solve both problems, your code should look something like
unsigned char buf[256] = { 0 }; // Arbitrary size, all initialized to zero
unsigned short size = 0; // To make sure it's properly initialized
get_result(buf + 4, &size); // Note use of & to pass a pointer to the variable size
Note that it works using an array, since arrays naturally decays to pointers to its first element.
buf in main is never initialized, so it points to some random location in memory. This is undefined behavior and a perfect recipe for a segfault.
Similarly, *size is read from when you use +=, but the value was never initialized in main, so your dereference an undefined value.
You should declare buf as an array of sufficient size and pass that in. Also, declare size as an int, initialize it to 0, and pass its address:
int main(int argc, char **argv)
{
unsigned char buf[100];
unsigned short size = 0;
// I'm assuming this was a typo and you ment to call get_result instead of test_result
get_result(buf, &size);
return 0;
}
Related
I'm reproducing printf from scrap and I need to store pointers address into a string then print it, so first I cast void* into an unsigned int then itoa it to hexadecimal but the last three char are wrong.
int main(void)
{
char str[] = "printf from scrap!";
my_printf("MY_PRINTF:'%p'", (void*)str);
printf("\n PRINTF:'%p'\n\n", (void*)str);
return (0);
}
int conv_p(va_list args)
{
void *ptr;
unsigned int ptrint;
ptr = va_arg(args, void*);
ptrint = (unsigned int)&ptr;
my_putstr("0x7fff");
my_putstr(my_itoa_base_uint(ptrint, 16));
return (1);
}
Output:
MY_PRINTF:'0x7fff505247b0'
PRINTF:'0x7fff50524a20'
As you can see the last three char are wrong, is there any documentation about that?
In the second case, you're converting the address of the variable ptr to an int, rather than its value (the pointer you're interested in).
Replacing (unsigned int)&ptr; with (unsigned int)ptr; will give you consistent values.
And an additional aside: there's no guarantee unsigned int is large enough to represent the pointer value: you should use intptr_t or uintptr_t from <stdint.h>.
My question is about dereferencing a char pointer
Here is my code -
#define MAX 10
char s[80]="Hello";
int main(){
char *stackValue;
stackValue=&s;//here I assined the address of s to stackValue
if(!stackValue){
printf("No place for Value");
exit(1);
}
else{
printf("\n%s",*stackValue);//This doesn't work with * before it
printf("\n%s",stackValue);//This works properly
}
return 0;
}
In the above code I have assigned the address of S[] to stackValue and when I am printing *stackValue it doesn't work ,
But If I print only 'stackValue' That works.
When I do same thing with Integer
int main(){
int i=10, *a;
a=&i;
printf("%d",*a);//this gives the value
printf("%d",a)//this gives the address
return 0;
}
Is printing char pointer and integer pointer is different. When I use * in int value it gives the value but gives an error when I use it as a char pointer.
Help me out?
With the first code snippet:
stackValue=&s; is incorrect given s is already an array to char. If you write like that then stackValue becomes pointer to pointer to char (not pointer to char).
Fix that by changing to stackValue=s;
Also, again %s expect a pointer to char (NOT pointer to pointer to char) - that explains why this doesn't work
printf("\n%s",*stackValue); // this doesn't work
You need printf("\n%s",stackValue); instead.
With the second code snippet.
a=&i; is ok because i is a single int, NOT an array.
What you are trying to do is this:
int main(void)
{
char a_data = "Hello, this is example";
char *pa_stack[] = {a_data};
printf("We have: %s\n", *pa_stack);
}
The "%s" format specifier for printf always expects a char* argument.
so this is working and correct statement
printf("\n%s",stackValue);
and in first statement you are passing value so it will give you undefined behaviour.
I want to find size or length of an unsigned char pointer in a function where that pointer is an argument to that function.Near the pointers declaration size is coming correctly.
But when i am trying to find size in function it is giving 4.
How can i do this ?
#include <stdio.h>
//void writeFile(unsigned char *da);
void writeFile(char *da);
int main(int arc,char **argv)
{
unsigned char block_bmp[]=
{
0x0,0xff,0xff,0xff,0x0,0x0,0x0,0xff,0xff,0xff,0x0,0x0,0x0,0xff,0xff,0xff,//*16bytes*
};
printf("size::%d\n",sizeof(block_bmp));
writeFile(block_bmp);
}
//void writeFile(unsigned char *da)
void writeFile(char *da)
{
printf("%d\n",__LINE__);
printf("size::%d\n",sizeof(da));
printf("length::%d\n",strlen(da));
FILE *fp;
int i;
fp=fopen("/tmp/hexfile","wb");
for(i=0;i<3780;i++)
fprintf(fp,"%c",da[i]);
// fwrite(da,sizeof(unsigned char),sizeof(da),fp);
fclose(fp);
}
If it points to a NULL-terminated string, use strlen. If not, the pointer is just some memory address for the called function, without any additional information about the size of the array (I assume, you try to pass an array). I suggest passing the number of array elements as additional parameter to the function.
You can not use sizeof in this condition. You should be using the strlen if the char array is NULL terminated.
When you pass array to a function, it decays to pointer, you can't use sizeof on this pointer to get the size of the array. The sizeof will give you 4 bytes (assuming 32 bit machine).
Example:
#include <stdio.h>
void fun(int myArray[10])
{
int i = sizeof(myArray);
printf("Size of myArray = %d\n", i);
}
int main(void)
{
// Initialize all elements of myArray to 0
int myArray[10] = {0};
fun(myArray);
getch();
return 0;
}
/**************OUTPUT**************
Size of myArray = 4
***********************************/
unsigned char array[100];
// sizeof(array) == 100
unsigned char* ptr = array;
// sizeof(ptr) == 4 for 32 bit platform.
When you call a function such as
foo(unsigned char* ptr)
{
}
with 'array' as argument, you only see a 'unsigned char *', not an array with 100 elements. That's why 'sizeof' returns 4.
pointers size sizeof(any_pointer_variable) will not depend on the datatype to which it is going to point. The size of the pointer is mostly 4 that is what you are getting in function. and it doesnt depend on what it points to. all pointers will have same size independent of what type they point to.
How do you pass an array to a function where that function can edit it's contents?
like when doing
function(int *x)
{*x = 10;}
main()
{int x;
function(&x);}
how could i do the same using a character array?
whenever I do
function(char *array[], int *num)
{ int x = *num;
*array[x] = 'A'; }
main()
{ char this[5] = "00000"; //not a string
int x = 3;
function(&this, &x); }
DEV C++ says
[Warning] passing arg 1 of `function' from incompatible pointer type
obviously I did something wrong, so please tell me how to fix that. Thanks :D
You should write:
void function(char array[], int *num)
{
int x = *num;
array[x] = 'A';
}
void main()
{
char my_array[5] = "00000";
int x = 3;
function(my_array, &x);
}
Notation char *array[] is an array of pointers that you do not need here.
When you pass an array somewhere, you should not take its address. Arrays are adjusted to pointers by default.
EDIT:
Function prototypes:
void function(char array[], int *num);
void function(char *array, int *num);
are absolutely identical. There is no even minor difference between them.
Since arrays can only be passed by address, you don't really want a char * array here, just a char array:
rettype function(char *array, int *num)
{
array[*num] = 'A';
}
int main()
{
char arr[] = "1234567890";
int i = 2;
function(arr, &i);
}
In C, array names "devolve" to a pointer to the head of the array, by passing "&array", you're passing a pointer to a pointer to the head of the array, thus the warning.
char array[512];
myfunc(array, foo);
is the proper way to do what you want.
Actually you have taken one dimension array. So you can define function in two ways...
(i)
function(char array[], int *num)
{ int x = *num;
*array[x] = 'A'; }
main()
{ char this[5] = "00000"; //not a string
int x = 3;
function(this, &x); }
and
(ii)
function(char *array, int *num)
{ int x = *num;
*array[x] = 'A'; }
main()
{ char this[5] = "00000"; //not a string
int x = 3;
function(this, &x); }
But in your function definition, you wrote *array[] as argument which means the array is two dimensional array. So you should declare array as two dimensional array.
function(char *array[], int *num)
{ int x = *num;
//implement your code }
main()
{ char this[5][10];
// you can initialize this array.
int x = 3;
function(this, &x); }
I think it will be helpful to you.
Okay, the first thing to remember is that there's no such thing as a pointer "to an array" although you'll hear that said fairly often. It's sloppy.
(As pointed out below, the terminology "pointer to an array" does strictly have a meaning -- but I maintain that you've been confused by it. What really happens is that every pointer contains an address. Depending on the declaration, the compiler can identify if it's being used correctly in context, and that's what your error message is really telling you: what you declared in the function is a pointer to an array of chars, which is to say the same thing as a char **, instead of a char *, which is what you're passing. But char *, or char **, or char ******, the important point is that you're making it too complex -- you already have the address you need identified by the array name.)
Pointers is pointers, they're addresses.
An array in C is simply an allocated chunk of memory, and it's name represents the address of the first element. So
char a[42];
is a block of memory 42 char's long, and a is its address.
You could rewrite your second function as
void foo(char* a, int num){ // (3)
// notice that you don't need the word function and
// for lots of reasons I wouldn't use it as a function name.
a[num] = 'A'; // (4)
}
int main(){
// Sadly "00000" IS a string no matter what your comment
// says. Use an array initializer instead.
char arry[5] = {'0','0','0','0','0' } ; // (1)
foo(arry,3); // (2)
}
This does what I believe your code means to do. Note that
(1) Since "00000" really is a string, it's actually creating an array 6 elements long which could have been initialized with the array initializer
{'0','0','0','0','0', 0 }
(2) The array (which I named 'arry' instead of 'this' since 'this' is often a keyword in C-like languages, why risk confusion?) is already an address (but not a pointer. It can be on the right-hand side of an assignment to a pointer, but not on the left hand side.)
So when I call
foo(arry,3);
I'm calling foo with the address of the first element of arry, and the number 3 (you don't need to declare a variable for that.)
Now, I could have also written it as
foo(&arry[0],3);
You would read that as "find the 0-th element of arry, take its address." It is an identity in C that for any array
char c[len];
the expression c and &c[0] refer to the same address.
(3) that could also be defined as foo(char arry[], int num). Those are equivalent.
(4) and when you refer to a[num] you're referring directly to the num-th element of the memory pointed to by a, which is at the address of the start of the array arry. You don't need all that dereferencing.
Don't be disturbed that this is a little hard to follow -- it's tough for everyone when they start C.
Firstly dont use this as a variable name, its a C++ keyword. Sorry didnt realise it was a C question.
main()
{
char foo[5] = "00000"; //not a string
int x = 3;
function(foo, &x);
}
You dont take the memory address of foo. foo when used in a pointer-accepting context degrades into a pointer to the first element. *foo is the same as foo[0] which is the same as *(foo + 0)
like wise foo[3] is the same as *(foo + 3) (the compiler takes care of multiplying the element size).
Here is the full code of it
#include <stdio.h>
#include <string.h>
void reverse_string(unsigned short *buf, int length)
{
int i;
unsigned short temp;
for (i = 0; i < length / 2; i++)
{
temp = buf[i];
buf[i] = buf[length - i - 1];
buf[length - i - 1] = temp;
}
}
int main(int argc, char **argv)
{
unsigned short* tmp = (unsigned short*)argv[1];
reverse_string(tmp,strlen(argv[1]) / 2);
printf("%s",argv[1]);
return 0;
}
As you can see, in main, we have
unsigned short* tmp = (unsigned short*)argv[1];
Arent pointers supposed to point "to the address of" of a variable? The one above isn't(using the ampersand). Yet the program works as intended.
Why is it like that?
And what does this part mean?
(unsigned short*)argv[1]
argv is a pointer-to-an-array-of-pointers:
argv[0][0] (a char)
argv[0] (a char*)
argv (a char**)
unsigned char* tmp = (unsigned char*)argv[1];
...works, because you're referencing the the second "string" in that set.
Note that in this case, "char" and "unsigned short" might be roughly equivolent depending on the compiler and platform, but it is probably not a good idea to assume that. For example, if you compiled to enable a "unicode" command line, then you might get "short" instead of "char" forwarded to you from the command line. But, that may be a dangerous assumption, as "these days" a "short" is usually 16-bits and a "char" is usually 8-bits.
Addressing the original questions:
argv is an array of pointers, each of which point to a character array. argv[1] is a pointer to the character array with the first argument (i.e. if you run ./program arg1 arg2, the pointer argv[1] points to the string arg1).
The ampersand is used to denote a reference, which is for most purposes the same as a pointer. It is syntactic sugar to make it easy to pass a reference to a variable that you have already declared. The common example is using scanf.
int x = 1;
scanf(..., &x, ...)
is equivalent to
int x = 1;
int *p = &x;
scanf(..., p, ...)
The program itself is designed to flip endianness. It's not sufficient to go character-by-character because you have to flip two bytes at a time (ie short-by-short), which is why it works using shorts.
(unsigned short*)argv[1] instructs the compiler to treat the address as if it were an array of shorts. To give an example:
unsigned char *c = (unsigned char *)argv[1];
c[1]; /*this points to the address one byte after argv*/
unsigned short *s = (unsigned short *)argv[1];
s[1]; /*this points to the address two bytes after argv */
Take a look at a primer on type casting.