C pointers - pass by value - c

I want to know why is it that when i call readF() and have it return the buffer pointer and i print the buffer in main() it prints the actual data and not the memory address? I am returning the address and not the actual data correct? In my main i have a pointer that points to what gets returned, which is just what the buffer pointer in readF() points to.
char *readF(){
char *buffer=NULL;
//allocate memory to contain the string plus null terminator
buffer=malloc((sizeof(char)*4)+1);
//fill memory with string Hello plus terminator
return buffer;
}
int main(int argc, char **argv){
char *buffer;
buffer=readF();
printf("%s", buffer);
return 0;
}

You print the actual data inside the buffer because you use the %s format specified in your printf statement. This tells printf to assume the pointer it receives, buffer in this case for the first specifier, is a pointer to a NULL-terminated character string, so it prints the string.
If you want to print the address use the %p format specifier
You're correct when you say the readF function is returning the memory address. It returns the memory address of the first byte of the buffer, ie a pointer to the buffer you allocate.
Note: at the end of your function you should really free(buffer) too :)

To print the address you need %p specifier.
Change
printf("%s", buffer);
to
printf("%p", (void *)buffer);

Related

Why char * c = NULL; causes an error in the following code?

My understanding:
char * c means c is pointing nothing.
When I type "Hello World", c is now pointing the first address of "Hello World".
It should print H and e, but I got "Segmentation fault: 11" error.
Can anyone please enlighten me why and how char * c = NULL; is causing an error?
Thanks in advance!
#include <stdio.h>
int main(void)
{
char * c = NULL;
gets(c);
printf("%c, %c\n", c[0], c[1]);
return 0;
}
gets doesn't allocate memory. Your pointer is pointing to NULL, which cannot be written to, so when gets tries to write the first character there, you seg fault.
The solution is:
Use a stack or global array (char c[1000];) or a pointer to dynamically allocated memory (char *c = malloc(1000);), not a NULL pointer.
Never use gets, which is intrinsically broken/insecure (it can't limit the read to match the size of the available buffer); use fgets instead.
char *c = NULL; declares the pointer c initialized to NULL. It is a pointer to nowhere.
Recall, A pointer is just a variable that holds the address to something else as its value. Where you normally think of a variable holding an immediate values, such as int a = 5;, a pointer would simply hold the address where 5 is stored in memory, e.g. int *b = &a;. Before you can use a pointer to cause data to be stored in memory -- the pointer must hold the address for (e.g. it must point to) the beginning of a valid block of memory that you have access to.
You can either provide that valid block of memory by assigning the address of an array to your pointer (where the pointer points to where the array is stored on the stack), or you can allocate a block of memory (using malloc, calloc or realloc) and assign the beginning address for that block to your pointer. (don't forget to free() what you allocate).
The simplest way is to declare a character array and then assign the address to the first element to your pointer (an array is converted to a pointer to the first element on access, so simply assigning the character array to your pointer is fine). For example with the array buf providing the storage and the pointer p holding the address of the first character in buf, you could do:
#include <stdio.h>
#include <string.h> /* for strcspn & strlen */
#define MAXC 1024 /* if you need a constant, #define one (or more) */
int main (void)
{
char buf[MAXC], /* an array of MAXC chars */
*p = buf; /* a pointer to buf */
if (fgets (p, MAXC, stdin)) { /* read line from stdin */
p[strcspn (p, "\n")] = 0; /* trim \n by overwriting with 0 */
if (strlen (p) > 1) { /* validate at least 2-chars */
printf("%c, %c\n", p[0], p[1]); /* output them */
}
}
return 0;
}
(note: strcspn above simply returns the number of character in your string up to the '\n' character allowing you to simply overwrite the '\n' included by fgets() with '\0' -- which is numerically equivalent to 0)
Example Use/Output
$ ./bin/fgetsmin
Hello
H, e
Look things over and let me know if you have further questions.

Why doesn't this C code change the string and cause a buffer overflow?

I wrote this code
#include <stdio.h>
int main()
{
char String[] = "Hello the world!";
char *pointer = String;
int i;
printf(" %s\n", pointer);
pointer = "Helllooooo the worlldddddd";
printf("Hello %s\n", pointer);
printf("Hello %s\n", String);
return 0;
}
but I can't understand how this line works fine.
pointer = "Helllooooo the worlldddddd";
but I got this output
Hello the world!
Hello Helllooooo the worlldddddd
Hello Hello the world!
As you see it couldn't change String value but it shows more than the original number of characters. Shouldn't this cause a buffer overflow? Won't that destroy other variables?
When you write the line
pointer="Helllooooo the worlldddddd";
you are not saying "take the array pointed at by pointer and overwrite its contents with the string "Helllooooo the worlldddddd"," but rather "change which string pointer points at so that it's now pointing at the string ""Helllooooo the worlldddddd"." This accounts for why you're seeing the original string printed out when you directly print String - you never actually modified it. As a result, you don't need to worry about overflowing your array here, since you're not actually writing anything to it.
On the other hand, if you wrote
strcpy(pointer, "Helllooooo the worlldddddd");
which actually does copy the contents of the new string into the buffer pointed at by pointer, then you would have a buffer overflow, which would be a problem. But notice that this is a very different operation that explicitly says "please copy the contents of this string to this location" rather than "change where this pointer points."
you have initialize a pointer which point to String "Hello the world " char *pointer=String; so far so good .
first printf printf(" %s\n",pointer);, you have printed the pointer which point to "Hello the world".
then you set the pointer to point anew string "Hellloooooo the worllddddd" pointer="Helllooooo the worlldddddd";.
then you have printed the pointer which point in this case to "Hellloooooo the worllddddd"printf("Hello %s\n",pointer); .
last printf you have printed the string "Hello the world" printf("Hello %s\n",String);.
Note:.
((takecare that you have printed in second printf("Hello %s\n",String); and third printf printf("Hello %s\n",String); the string hello which will be printed before the value of the pointer or the string))
#include <stdio.h>
int main()
{
char String[]="Hello the world"; // the string
char *pointer=String; // pointer to string
char i; //counter
printf(" %s\n",pointer); // print current value of pointer
pointer="number of char"; // new value to replace the string
for (i=0;i<14;i++) // you cannot change the content of array without using loop
{
String[i] = pointer[i]; // char i in string = ti char i in pointer
}
printf("Hello %s\n",pointer); // print value of pointer
printf("Hello %s\n",String); // print value of string
return 0;
}
i think that what are you trying to do.
One more quick option for you to consider when manipulating strings:
The string function strdup(...); allows the copying of an existing string into a newly created string in one easy step. (or at least one in which all the complexity has been abstracted away):
char *pointer = strdup("Helllooooo the worlldddddd");
The new string pointer can now be used to contain any string up to len long, where len is defined as:
int len = strlen(pointer);//len is 26 after using strdup(...); above
So for example, because your example string is shorter than len:
char String[]="Hello the world!";//length is 16
you could copy it into pointer without a buffer overflow:
strcpy(pointer, String);
Strings created using strdup(...): need to be free'd to avoid memory leaks. Call the following when you are finished using pointer:
free(pointer);

How to use a pointer to point only at half of an array

I'm new to C and pointers, so i have this problem. I want to tell to pointer how much memory it should point to.
char * pointer;
char arr[] = "Hello";
pointer = arr;
printf("%s \n", pointer);
This pointer will point to whole array, so i will get "Hello" on the screen. My question is how can i make pointer to only get "Hel".
You may try this:
char * pointer;
char arr[] = "Hello";
pointer = arr;
pointer[3] = '\0'; // null terminate of string
printf("%s \n", pointer);
If you always work with strings, then have a look at strlen for getting length of a string. If a string arr has length l, then you may set arr[l/2] = '\0', so that when you print arr, only its first half will be shown.
You may also want to print the last half of your string arr? You can use pointer to point to any place you want as the start. Back to your example, you may try:
char * pointer;
char arr[] = "Hello";
pointer = arr + 2; // point to arr[2]
printf("%s \n", pointer);
Have a check what you will get.
printf has the ability to print less than the full string, using the precision value in the format string. For a fixed number of characters (e.g. 3), it's as simple as
printf( "%.3s\n", pointer );
For a variable number of characters, use an asterisk for the precision, and pass the length before the pointer
int length = 3;
printf( "%.*s\n", length, pointer );
You don't know what a pointer is so I'll explain.
A pointer does not point to a string. It points to a char! Yes, a char. A string in C is really just a set of chars all one after the other in the memory.
A char* pointer points to the beginning of a string. The string ends when there is a '\0' (aka null) char. When you printf("%s",s), what printf does is a cycle like this:
int i;
for(i=0;1;i++) //infinite cycle
{
if(s[i]=='\0')
break;
printf("%c",s[i]);
}
Meaning it will not print a string but all the chars in a char array until it finds a null char or it goes into memory space that is not reserved to it (Segmentation fault).
To print just the 1st 3 characters you could do something like this:
void printString(char* s,int n) //n=number of characters you want to print
{
if(n>strlen(s))
n=strlen(s);
else if(n<0)
return;
char temp=s[n]; //save the character that is in the n'th position of s (counting since 0) so you can restore it later
s[n]='\0'; //put a '\0' where you want the printf to stop printing
printf("%s",s); //print the string until getting to the '\0' that you just put there
s[n]=temp; //restore the character that was there so you don't alter the string
}
Also, your declaration of pointer is unnecessary because it is pointing to the exact same position as arr. You can check this with printf("%p %p\n",arr,pointer);
How much of the string is printed is controlled by the NULL-character "\0", which C automatically appends to every string. If you wish to print out just a portion, either override a character in the string with a "\0", or use the fwrite function or something similar to write just a few bytes to stdout.
You could achieve the objective with a small function, say substring.
#include<stdio.h>
#include<string.h> // for accessing strlen function
void substring(char* c,int len)
{
if (len <= strlen(c)){
*(c+len)='\0';
printf("%s\n",c);
}
else{
printf("Sorry length, %d not allowed\n",len);
}
}
int main(void)
{
char c[]="teststring";
char* ptr=c;
substring(ptr,4); // 4 is where you wish to trim the string.
return 0;
}
Notes:
In C++ a built-in function called substring is already available which shouldn't be confused with this.
When a string is passed to a function like printf using a format specifier %s the function prints all the characters till it reaches a null character or \0. In essence, to trim a string c to 4 characters means you put c[4] to null. Since the count starts from 0, we are actually changing the 5th character though. Hope the example makes it more clear.

Copy character string to character pointer in C

Here is a simple program to demonstrate my problem.
I have a function functionB which passes pointer to a character array to functionA. functionA finds the value and stores it to a character array. The content of character array should be copied to character pointer fdate. How can I achieve this?
int functionB() {
char fdate[20];
functionA(&fdate[0]);
return 0;
}
int functionA(char *fdate) {
char date[20] = "20 May 2016";
strcpy(fdate, date);
return 0;
}
You cannot copy a string into a character pointer, but you can copy a string to a memory block pointed to by a character pointer. You cannot do this:
char *ptr;
functionA(ptr);
and expect ptr to point to the string. You need to pass a pointer to a valid memory block into your function, like this:
char buf[100];
functionA(buf);
Now the copy would work, but the function would be unsafe because it wouldn't know how much memory is available for writing its string, and could cause buffer overruns. A better approach is to pass the size of the buffer along with the buffer:
functionA(buf, sizeof(buf));
Another alternative is to pass a pointer to pointer, and have the function allocate the string dynamically. In this case, however, the caller is responsible for freeing the memory after its use:
char *ptr;
functionA(&ptr);
...
free(ptr);
...
int functionA(char **fdate) {
char date[20] = "20 May 2016";
*fdate = malloc(sizeof(date));
memcpy(*fdate, date);
return 0;
}

Why splitting the word in this way is crashing?

I executed the following code.
#include <stdio.h>
int main()
{char *a="awake";
printf("%s\n", *(a+1));
return 0; // expected out_put to be wake
}
You're dereferencing the pointer, which makes it a char but trying to output a string. Change your print statement to printf("%s\n", a+1);
*(a+1) is the same as a[1] which is a char, not the char * that printf expects for the %s.
EDIT: clarification: printf needs an address for the %s specifier, a+1 is such an address (namely the address of the second character in the string), but *(a+1) then gives the value at that address. Which is just a character and in all likelyhood not a valid memory location for printf to read.
You don't want to defrefeence the char *:
printf("%s\n", (a+1));
does what you want.

Resources