I'm trying to write into a byte that I have allocated using malloc(). I'm really struggling with correctly printing out the bits and the values.
int main(){
unsigned char *heap = (unsigned char *) malloc( 2 * sizeof(char)); //allocate two bytes
int n= 2, i =0;
unsigned char* byte_array = heap;
while (i < 2) //trying to write over the first byte then print out to verify
{
printf("%016X\n", heap[i]);
heap[i] = "AAA";
printf("%p\n", heap[i]);
i++;
}
}
This is the output I'm getting
0000000000000000
0xc7
0000000000000000
0xc7
To understand difference between "string" and 'c' character in C. Try this code:
#include <stdio.h>
int main(){
/* Usual way */
char *a = "A";
char *b = "B";
char *c = "C";
printf("Address of a = 0x%x\n",a);
printf("Address of b = 0x%x\n",b);
printf("Address of c = 0x%x\n",c);
/* Explicit way - Because you asked above question */
printf("This is Base Address of String A = 0x%x\n","A");
printf("This is Base Address of string B = 0x%x\n","B");
printf("This is Base Address of string C = 0x%x\n","C");
/* Now, let us print content - The usual way */
printf("Pointer value a has %x\n",*a);
printf("Pointer value b has %x\n",*b);
printf("Pointer value c has %x\n",*c);
/* The unusual way */
printf("Value of String A %x\n",*"A");
printf("Value of String B %x\n",*"B");
printf("Value of String C %x\n",*"C");
}
The above code will generate compiler warning because char * is formatted as unsigned int, but just ignore it to understand the example.
The output would look like following:
Address of a = 0xedfce4a
Address of b = 0xedfce4c
Address of c = 0xedfce4e
This is Base Address of String A = 0xedfce4a
This is Base Address of string B = 0xedfce4c
This is Base Address of string C = 0xedfce4e
Pointer value a has 41
Pointer value b has 42
Pointer value c has 43
Value of String A 41
Value of String B 42
Value of String C 43
First of all, you are doing some operations without really knowing the meaning:
while (i < 2)
{
printf("%016X\n", heap[i]); // You're printing the value of heap[i] in hexadecimal that
// is not even setted
heap[i] = "AAA"; // This operation has no sense, 'cause a
// "char" can only contain 1 character
printf("%p\n", heap[i]); // You are printing a pointer, why?
i++;
}
The char in C can contain only ONE character. So this has a sense:
char a = 'b';
and if you want to have a string you need an array of char:
char * a = "AAA";
For more read here
So I would rewrite the code in this way:
while (i < 2){
printf("First: %c\n",heap[i]);
heap[i] = 'a';
printf("After: %c\n",heap[i]);
i++;
}
Related
I try to understand when a variable's value gets modified by passing through a function in C.
I know that in C, there's two ways to change variable's value :
Using the return value of a function
Passing a variable's address to modify its content
Here's the code :
// by address
void foo(int *nb)
{
*nb = 10;
}
int main(void)
{
int nb = 5;
foo(&nb);
printf("%i\n", *nb); // It prints 10
}
// Code to explain
void foo(char **tab)
{
tab[2] = "44";
}
void bar(char *str)
{
str[1] = 'a';
}
int main(void)
{
char **tmp = malloc(sizeof(char *) * 4);
char *str = strdup("Hello");
for (int i = 0; i < 3; ++i)
tmp[i] = malloc(3);
tmp[0] = "11";
tmp[1] = "22";
tmp[2] = "33";
tmp[3] = NULL;
foo(tmp); // It modifies tmp's value
bar(str); // It modifies str's value
for (int i = 0; i < 3; ++i)
printf("%s\n", tmp[i]);
printf("%s\n", str);
}
Output:
11
22
44
Hallo
Expected:
11
22
33
Hello
I was expecting to send a copy to the function but at the end, both string and char ** are modified.
Why variables are modified here ?
Your comment on foo(tmp) says “It modifies tmp's value,” but this is not correct. tmp is a pointer, and the value of the pointer is not modified by foo. The call foo(tmp) passes the value of tmp to foo, and then foo modifies the things that are pointed to. It changes tmp[2] to point to "44". tmp[2] is one of the things pointed to by tmp; it is not tmp.
Similarly, in bar(str), str is a pointer, and the value of the pointer is not changed by var. Rather, bar changes one of the characters in the string that str points to.
I'm trying to accomplish the following:
given the function:
int f(void *p)
take the first byte of p and extract it as a character. Then based on what that character is determine which additional bytes to extract as short ints. For example if I have a certain character c then extract byte 4 and 7 as short ints and store them in separate variables; if I have a certain different character d extract bytes 3, 4, 5 and store them as separate variables. With this information execute some other irrelevant code. I've been struggling with this for hours.
I tried the following:
int f(void *p) {
char *first = &p;
short int *third = p + 2;
short int *fifth = p + 4;
short int *seventh = p + 6;
printf("%s %s %s, %s", first, third, fifth , seventh);
}
int main(int argc, char const *argv[]) {
char test[] = "*5431234567";
f(test);
}
My result:
▒▒ϲ -1295010922 -1295010920, -1295010918
Expected:
* 4 1 3
After a while I realized I was attempting to de-reference a void pointer which does not work. So I tried casting:
char* c = (char*) p;
char first = (char) (*c)
printf("%s", first);
This gave me a seg fault.
I tried similar things with short int casting to no avail. If this is a somewhat noobish question I apologize. I'm new to C and the whole concept of pointers and references is new to me. My first language was Java which is much more forgiving.
Your input is a string, and your expected output are individual characters within the string. There is nothing short int-like about this problem.
char *s = p;
printf("%c %c %c, %c", s[0], s[2], s[4] , s[6]);
If you need to store those values into short int variables, then you do not need pointers.
short int x = s[2] - '0';
short int y = s[4] - '0';
short int z = s[6] - '0';
printf("%c %hd %hd %hd\n", s[0], x, y, z);
The characters that represent the decimal digits are guaranteed to be contiguous, so you can compute the ordinal value by calculating the offset from '0'.
char *first = &p;
Get rid of the &. You don't want the address of the p variable, you want the address stored in it, which is simply p.
char *first = p;
short int *third = p + 2;
short int *fifth = p + 4;
short int *seventh = p + 6;
printf("%s %s %s, %s", first, third, fifth, seventh);
There's no reason to be using short pointers. The elements of a string are chars, not shorts. Even when they're digits, they're still chars.
Leave them as chars, switch to %c to print them, and make sure to dereference the pointers when you do.
char *third = p + 2;
char *fifth = p + 4;
char *seventh = p + 6;
printf("%c %c %c %c\n", *first, *third, *fifth, *seventh);
#include<stdio.h>
#include<stdlib.h>
struct test{
char b;
int a;
int c ;
};
int main()
{
struct test inst;
struct test *ptr_test = &inst;
char * ptr_ch;
int* ptr_i;
/*ptr_ch = (char *) ptr_test;*/
ptr_ch = (char*)ptr_test;
ptr_i = (int *) ptr_test;
*ptr_ch = 'b';
*ptr_i = 13;
printf("char b = %c, int a = %d int c = %d", inst.b, inst.a, inst.c);
return 0;
}
I expected the output to give the appropriate values of a,b and garbage value of c.
But on the terminal, if I do ./a.out the output is:
, int a = 134513785 int c = 13173540
When I do $./a.out > tmp; vim tmp, the output is:
char b = ^M, int a = 134513785 int c = 12714788
What is the problem?
I wanted to access individual fields of the struct using typecasting.
for instance, I wanted to know another way to return the value of &(inst.a).
Your pointers
ptr_ch = (char*)ptr_test;
ptr_i = (int *) ptr_test;
do not automatically refer to the first apropriate member variable (in your case b and a). Rather they just reinterpret the pointer to the structure as pointer to char or int, so they point to the same location, the address of your structure. With the char you might be lucky that it's the first member and you are really pointing to the char, but your int pointer points to the same address and therefore overwrites it with platform- and compiler-dependent garbage.
So don't do those kinds of things (or do them when you really know what you are doing and, more important, where (on what platform and with what compiler) you are doing it).
ptr_ch and ptr_i point to the same memory location:
ptr_ch = (char*)ptr_test;
ptr_i = (int *) ptr_test;
when you do the following you are reading from the same memory address:
*ptr_ch = 'b'; //write the first sizeof(char) byte of the structure ptr_test
*ptr_i = 13; //write the first sizeof(int) bytes of the structure ptr_test overwriting some bytes wrote before
You should eventually do something like:
ptr_ch = &(ptr_test->b);
*ptr_ch = 'b';
ptr_i = &(ptr_test->a);
*ptr_i = 13;
Why would you use the typecasting? Why not do the following:
ptr_ch = &(ptr_test->b);
ptr_i = &(ptr_test->a);
13 is decimal for an ASCII carriage return - when you do *ptr_i = 13;, you're setting b to that 13. If you change your print out to look like:
printf("char b = %c (%d), int a = %d int c = %d", inst.b, inst.b, inst.a, inst.c);
You'll see that you get:
(13), int a = 1 int c = 1606416024
as output instead. The carriage return character is causing your char b output to get overwritten by the output following the carriage return character. It might be more obvious if you used a different number than 13. For example, using 86, you'll get:
char b = V, int a = 1 int c = 1606416024
as the output. The reason a and c don't make sense is because they're uninitialized.
You can't just typecast a structure pointer to a pointer of another type and expect the compiler to extract a pointer to a field inside that structure for you - that's not how it works. I think you might have been trying to do this:
ptr_ch = &ptr_test->b;
ptr_i = &ptr_test->a;
Here's a complete example program that does what I think you're trying for:
#include<stdio.h>
struct test {
char b;
int a;
int c;
};
int main(void)
{
struct test inst = {0, 0, 0};
struct test *ptr_test = &inst;
char *ptr_ch;
int *ptr_i;
ptr_ch = &ptr_test->b;
ptr_i = &ptr_test->a;
*ptr_ch = 'b';
*ptr_i = 86;
printf("char b = %c, int a = %d int c = %d\n", inst.b, inst.a, inst.c);
return 0;
}
And its output:
char b = b, int a = 86 int c = 0
You should use the strict conforming offsetof macro, which calculates the offset of any struct element from struct begin:
ptr_ch = (char*)ptr_test;
*ptr_ch = 'b';
ptr_i = ptr_ch + offsetof(struct test,a);
*ptr_i = 13;
ptr_i = ptr_ch + offsetof(struct test,c);
*ptr_i = 14;
Trying to learn pointers better I wrote this code. The intention was to print one character of a string at a time in a for loop. Again trying to learn how to increment a pointer and then dereference the pointer.
char *string = "abcdef";
char *pointer = &string;
for (int i =0; i < 4; i++)
{
printf("the next charater is %c\n", *pointer);
pointer = (char *)pointer + sizeof(char);
}
want it to print:
the next charater is a
the next charater is b
the next charater is c
the next charater is d
char *pointer = &string;
should be
char *pointer = string;
string is a pointer variable that contains the address of your string literal. You want the address of the string literal, so you should simply copy the value in string - not take the address of the local pointer variable - your current code gives you a pointer to a pointer to a string.
Additionally, pointer = (char *)pointer + sizeof(char); doesn't require a cast, and it should not use sizeof(char). When incrementing a variable of type pointer to X, incrementing it by one will increment it by sizeof(X) bytes - increment by one to point at the next X. Use pointer += 1; or ++pointer instead.
If you want to print (or otherwise process) the whole string one char at a time, you may use the following idiom:
char *p = /* ... */;
while (p && *p) {
printf("next char: %c\n", *p++);
}
The condition first tests whether p is NULL, i.e. if it is wise to dereference p at all. If p is not NULL, *p tests whether you already reached the end of the string, denoted by the '\0' character, which happens to be 0.
If you want to use pointer to pointer to string then you can use like this:
char *string = "abcdef";
char **pointer = &string;
int i;
for (i =0; i < 4; i++)
{
printf("the next charater is %c\n", **pointer);
*pointer = *pointer + sizeof(char);
}
AFunc changes what was sent to it, and the printf() outputs the changes:
void AFunc ( char *myStr, int *myNum )
{
*myStr = 's';
*myNum = 9;
}
int main ( int argc, char *argv[] )
{
char someString = 'm';
int n = 6;
AFunc(&someString, &n);
printf("%c" "%d", someString, n);
}
But what if the string was more than one char? How would the code look differently? Thanks for any help.
If it were a "string" instead of a char, you would do something like this:
#include <stdio.h>
void AFunc (char *myStr, int *myNum) {
myStr[0] = 'p'; // or replace the lot with strcpy(myStr, "pax");
myStr[1] = 'a';
myStr[2] = 'x';
myStr[3] = '\0';
*myNum = 9;
}
int main (void) {
char someString[4];
int n = 6;
AFunc(someString, &n);
printf("%s %d", someString, n);
return 0;
}
which outputs:
pax 9
A "string" in C is really an array of characters terminated by the \0 (NUL) character.
What the above code does is to pass in the address of the first character in that array and the function populates the four characters starting from there.
In C, a pointer to char isn't necessarily a string. In other words, just because you have char *x;, it doesn't mean that x is a string.
To be a string, x must point to a suitably allocated region which has a 0 in it somewhere. The data from the first character that x points to and up to the 0 is a string. Here are some examples of strings in C:
char x[5] = {0}; /* string of length 0 */
char x[] = "hello"; /* string of length 5, the array length being 6 */
char *x = "hello"; /* string of length 5. x is a pointer to a read-only buffer of 6 chars */
char *x = malloc(10);
if (x != NULL) {
strcpy(x, "hello"); /* x is now a string of length 5. x points
to 10 chars of useful memory */
}
The following are not strings:
char x[5] = "hello"; /* no terminating 0 */
char y = 1;
char *x = &y; /* no terminating 0 */
So now in your code, AFunc's first parameter, even though is a char * isn't necessarily a string. In fact, in your example, it isn't, since it only points to a memory that has one useful element, and that's not zero.
Depending upon how you want to change the string, and how the string was created, there are several options.
For example, if the myStr points to a writable memory, you could do something like this:
/* modify the data pointed to by 'data' of length 'len' */
void modify_in_place(char *data, size_t len)
{
size_t i;
for (i=0; i < len; ++i)
data[i] = 42 + i;
}
Another slightly different way would be for the function to modify data until it sees the terminating 0:
void modify_in_place2(char *data)
{
size_t i;
for (i=0; data[i]; ++i)
data[i] = 42 + i;
}
You are only dealing with chars and char pointers. None of the char pointers are valid strings as they are not null terminated.
Try defining a string and see what it looks like.
But what if the string was more than one char? How would the code look
differently? Thanks for any help
Ofcourse, you would modify the other characters as well, but in the exact same way you did the first time.
Declare a char array and pass its address
Modify values at those address
A char array would be a more clear term for a string.