void main()
{
printf("ABCD");
printf("\n");
printf("ABCD" +1);
printf("\n");
printf("ABCD" +3);
}
Outputs is:
ABCD
BCD
D
Can anyone explain me why?
"ABCD" is actually an array of characters {'A','B','C','D', '\0'} (where '\0' is the trailing null byte). If you add 3 to that, then that is the equivalent of advancing a pointer 3 bytes forward from A, so you end up pointing at D.
Question 6.2 in the C FAQ has a picture that makes this clearer. The array decays to a pointer as described in 6.4 so you have the situation of the variable p.
char a[] = "hello";
char *p = "world";
"ABCD" is treated as a pointer to a block of memory containing four characters followed by a null terminator (\0).
"ABCD" + 1 adds 1 to the pointer, causing it to point one byte further.
Related
I'm new to C, so I'm still trying to get used to some of the concepts, so apologies if this sounds like a dumb question.
I'm given a void pointer, and I have to check that if the first element of it is equal to 1 when casting it as a char pointer. I basically have to solve the following:
void* ptr;
//Ensure that ((char*)ptr)[0] == 1
So far, what I have is:
void* ptr = malloc(4);
char* temp = "f";
ptr = temp;
I'm still trying to get used to comparing chars and ints in C. I recently learned that it compares their ASCII values. Wouldn't that mean that the since the first number in the ASCII value for "f" is 1 (102), it would mean that ((char*)ptr)[0] == 1? This is probably wrong, but I'm not sure how to fix it. I also know that the C char with an ASCII value of exactly 1 is ^A. I'm not sure how to enter that in as a char* since it just interprets the whole thing as two chars (the ^ and the A).
How am I supposed to set ((char*)ptr)[0] equal to 1? I'm pretty lost on this right now.
This code is not doing what you think it does. THe compiler must be screaming at you about it.
void* ptr = malloc(4);
char* temp = "f";
ptr = temp;
I think you are trying to allocate a 4 byte buffer and then set the first byte of that buffer to "f"
void* ptr = malloc(4);
*((char*)ptr) = 'f';
The first line allocates 4 bytes and puts the pointer to it in ptr
Second line says , treat ptr as a char ptr, put 'f' where that char pointer points.
Easier to read is
// make a copy of ptr saying its a char ptr
char *temp = (char*)ptr;
// store f where it points
*temp = 'f'
Note 'f' not "f". These are 2 different things
'f' is the single char = hex 0x66 or decimal 102 (https://www.asciitable.com/)
"f" is a character string composed of 2 bytes 'f' and '\0'
You can specify character codes in a string using octal or hexadecimal escape sequences. So the following will create a string whose first byte is 1 and will satisfy the test in your code.
char *f = "\1"; // or "\x1"
You're right that the proper way to check if the first character is a 1 is ((char*)ptr)[0] == 1.
I recently learned that it compares their ASCII values.
In C, character values are just integers. For example, the character literal 'f' is 102 (assuming you're using ASCII). That means the following is perfectly valid.
int x = 'f';
if ( x > 100 ) {
printf("Greater than 100\n");
}
It's not the case that the first character is 1, the second 0, and the third 2. 'f' and 102 are the same thing.
On a side note (but a very important one), you've got a memory leak in your code, as #WhozCraig pointed out in the comments. You're assigning ptr to malloc(4) but then reassigning ptr to temp. Therefore, the four bytes allocated by the malloc call are lost.
You can just do
void *ptr;
char *temp = "f";
ptr = temp;
I am learning Pointers for the first time from c K&R there was a question about creating your own Strcat function with the help of pointers and stumbled upon few things which i could not understand . I made use of printf statements to understand a part of what was going on but i am still couldn't grasp it completely .
Code:-
void *Strcat(char *a , char *b)
{
printf("*a =%c\n" , *a ) ;
while ( *a != '\0' )
++a ;
printf("*a =%c\n" , *a ) ;
*a++ = *b++ ;
printf("a =%s\n" , a ) ;
printf("*b =%c\n" , *b ) ;
while( *a++ = *b++ ) ;
}
int main(int argc , char *argv[])
{
char s[] = "Hello" ;
char t[] = "World" ;
Strcat( s, t) ;
printf("s=%s\n" , s) ;
printf("t=%s\n",t) ;
return 0 ;
}
PS- I realized that i created a pointer to null function , initially it was pointer to char to imitate the original library function but during testing i changed it to void to remove complexities . Sorry for that
Output :-
*a =H
*a =
a =World
*b =o
s=HelloWorld
t=orld
My shortcomings :-
1. a=World // 3rd output Line
I understand '%s' reads untill '\0' character . By using *a++ = *b++ I was expecting that i was just equating the value present at that memory adress(of a) with one at b but i guess there's more to it since the output is "World"
2. t=orld
I guess i somehow changed the base adress of t as well but i thought that by passing adress of the array i would just be changing the values at the given memory address but i somehow changed its base address as well
3. If any one could explain my concoction that Strcat has become
I want to thank everyone who went through my entire long post even if you couldn't help me , it means a lot to me . So thanx for helping a fellow beginner out!!!
When you create a string as:
char str[] = "World";
The length of str will be 6 (its characters plus the null terminating character).
If you try to add values after it using pointers, what you're doing is accessing invalid memory, because that memory doesn't belong to your string; because you created your string with 6 bytes, it can put it anywhere in memory, hence, the other memory might belong to something important that you may not change.
What you could've done is created your first string with a specified length:
char s[11] = "Hello";
Because HelloWorld\0 is 11 bytes wide, you can create an array of chars with 11 bytes.
Now you may be wondering: "What if I wanted to work with generic length strings?"
Then, you'd have to use dynamic memory for that.
EDIT:
To answer your question:
I understand '%s' reads untill '\0' character . By using *a++ = *b++ I was expecting that i was just equating the value present at that memory adress(of a) with one at b but i guess there's more to it since the output is "World"
The output is just World because once you tried to change it, it didn't let you, because its memory was invalid (as explained earlier). Because of that, the string remained the same as it started.
This has nothing to do with pointers directly; man strcat:
The strcat() function appends the src string to the dest string,
overwriting the terminating null byte ('\0') at the end of dest, and then adds a terminating null byte.
The strings may not overlap, and the dest string must have enough
space for the result.
If dest is not large enough, program
behavior is unpredictable; buffer overruns are a favorite avenue for
attacking secure programs.
while ( *a != '\0' )
++a ;
This fast-forwards the pointer a to the end of the string which is in this case also the end of the allocated memory. Any further increment and access will give UB. But this is not strcat's problem: it is the caller's responsability.
With an additional string:
char t[] = "World" ;
char x[] = "uuuuuuuuuu" ;
char s[] = "Hello" ;
you see the confusion:
*a =H
*a =
a =uuuuuuuuuu
*b =o
s=HelloWorld
t=World
x=orld
Hi I'm new to programming.
In the following code str is a pointer to a character, so str should contain the address of the character 'h'. Therefore %p should be used to print that address. But I don't understand how %s is used for printing a pointer parameter.
#include<stdio.h>
int main (){
char s[] = "hello";
char *str = s;
int a[] = {1, 2, 3, 4, 5};
int *b = a;
printf("%s\n", str); // I don't understand how this works ?
printf("%c\n", *str); // This statement makes sense
printf("%c\n", *(str + 1)); // This statement also makes sense.
printf("%p\n",str); // This prints the address of the pointer str. This too makes sense.
printf("%d\n",*b); // makes sense, is the same as the second print.
// printf("%d",b); // I don't understand why str pointer works but this gives a compile error
return 0;
}
char s[] = "hello";
Declares an array of zero-terminated characters called s. Its the same as writing
char s[6] = { 'h', 'e', 'l', 'l', 'o', '\0' };
As you can see, the quotation marks are a shorthand.
char *str = s;
This declares str to be a pointer to a character. It then makes str point to the first character in s. In other words, str contains the address of the first character in s.
int a[] = {1, 2, 3, 4, 5};
Declares an array of integers. It initializes them to the values 1-5, inclusive.
int *b = a;
Declares b to be a pointer to an int. It then makes b point to the first int in a.
printf("%s\n", str);
The %s specifier accepts the address of the first character in the string. printf then walks from that address, printing the characters it sees, until it sees the \0 character at the end.
printf("%c\n", *str);
This prints the first character in str. Since str is pointing to a character (the first character in the string), then *str should obtain the character being pointed at (the first character in the string).
printf("%c\n", *(str + 1));
This prints the second character in str. This is the long way of writing str[1]. The logic behind this is pointer arithmetic. If str is the address of a character, then str + 1 is the address of the next character in the array. Since (str + 1) is an address, it may be dereferenced. Thus, the * obtains the character 1 character past the first character of the array.
printf("%p\n",str);
The %p specifier expects a pointer, just like %s would, but it does something else. Instead of printing the contents of a string, it simply prints the address the pointer is containing, in hex.
printf("%d\n",*b);
This prints the first int in the array pointed to by b. This is equivalent to writing b[0].
printf("%d",b);
b is an int *, not an int, which is what %d expects. If you were trying to print the address of the first element of the array, the specifier would be %p, not %d. Also, this line should not generate a compiler error. Instead, it should have been a runtime undefined behavior, since the compiler does not know what a printf format string is.
if you point a char pointer to a chunk of memory that you just malloc() and feed it characters at position [0], [1], [2], [3],..., [n] does malloc already provide a null terminator '\0' at the end or must i provide it at the last element of the char array?
int i;
char B; //has the characters hello
char *A=malloc(5*sizeof(char)); //4 bytes for hello + 1 byte for null terminator?
for(i=0; i<strlen(A);i++)
A[i]=B[i];
after the for loop finishes should i add a null terminator to the last element of A or does malloc() already provide it?
YES you need to put a null terminator explicitly. malloc is just returning starting pointer to the block of 5 byte memory.
After malloc, A contains garbage value, so you need to assign \0 explicitly. However, there are several other errors in your code:
Your declaration of B is wrong, it should be a char array instead of a single char.
The string "hello" contains 6 elements, including the trailing \0, so:
char B[] = "hello";
char *A = malloc(strlen(B) + 1);
for(i = 0; i < strlen(B) + 1; i++)
A[i] = B[i];
Or you can simply use strcpy:
strcpy(A, B);
Malloc will not provide memory filled with nulls.
As pointed out above, use strcpy and be safe.
I edited out the calloc part. That was wrong.
I was just wondering why the output for this code I have below is abcdef def instead of abc def.
main()
{
char array1[3]="abc";
array1[3]='\0';
char array2[3]="def";
array2[3]='\0';
printf("%s %s", array1, array2);
}
char array1[3]="abc";
array1[3]='\0';
char array2[3]="def";
array2[3]='\0';
array1[3]='\0'; and array2[3]='\0'; statements access arrays out of bounds and invoke undefined behavior. The last element of an array of 3 elements is array1[2] not array[3].
To fix your program, declare your arrays as:
char array1[]="abc";
char array2[]="def";
And don't manually add the null terminator as it will be already included in the declaration above.
EDIT:
some other answers incorrectly assume that
char array1[3]="abc";
would write a trailing null character outside the array. Actually no trailing null character is written in this initialization. The declaration is equivalent to:
char array1[3]= {'a', 'b', 'c'};
When you do:
char array1[3]="abc";
Then array1[3] is out of bounds.
You should do:
char array1[4]="abc"; //Remember the '\0'
^^^
Note that the '\0' will be added in this way.
Also please note that when you have array of size N, then the indexes are from 0 to N - 1.
In your code
main()
{
char array1[3]="abc"; //Undefined ,when you access this using printf() with %s
array1[3]='\0'; //here you are storing value which is out of bound in nature
char array2[3]="def"; //same as above
array2[3]='\0'; //same as above
printf("%s %s", array1, array2);
}
memory:
---------------
| a | b | c |\0|
----------------
The last \0 what you are putting is more than the space you have allocated.
solution:
main()
{
char array1[4]="abc";
//array1[3]='\0'; //no need
char array2[4]="def";
// array2[3]='\0'; //no need
printf("%s %s", array1, array2);
}
It will give desired output
This is such a bad code! What is happening is the following:
Compiler allocated space for 2x3 chars.
main()
{
char array1[3]="abc"; //Will write "abc" in array 1 AND \0 in array2[0]
array1[3]='\0'; //Out of array!!! (Re)writing \0 in array2[0]
char array2[3]="def"; //Will write "def" in array2 AND \0 after array2 space, POTTENCIALLY corrupting code!
array2[3]='\0'; //\0 (re)wrote after array2, POTTENCIALLY corrupting code!
What you have in memory is 7 bytes (just 6 were allocated): "abcdef\0".
Pointes still ok: array1 points "a" and array2 points "d".
In C standard libraries, strings sizes are determined by ending zero terminator. So when you printf array1, it will read "abcdef" until \0.