C pointer question (main versus function parameters) - c

I am really struggling with pointers in C. Specifically, I have been having trouble understanding how to work with pointers when they are in main versus when I input a pointer into a function parameter from main.
I have a few scenario questions about them that hopefully someone can answer:
int main (int argc, char* argv[]) {
int x = 7;
int* num = 4;
char* word = "johnny";
//Q1. how do I get the address of 'num'?
//Q2. how do I get the address of 'x'? (should I be using x's or num's address?)
//Q2. how do I get the value of 'num'?
//Q3. how do I get the address of 'word'?
//Q4. how do I get the whole string for 'word'?
//Q5. how do I get an individual character in 'word'? (for index 0 ('j') and index 3 ('n'))
}
bool some_func (int* count, char** name) {
//Q6. how do I get the address of the inputted 'count'?
//Q7. how do I get the value of the inputted 'count'?
//Q8. how do I get the address of the inputted string 'name'?
//Q9. how do I get the whole string of the inputted string 'name'?
//Q10. how do I get an individual character of the inputted string 'name'? (for index 0 ('j') and index 3 ('n'))
}
For my recent homework assignments, I've been given intimidating headers like these and I don't know how to get the values that I want out of them. Say I found out that saying '*name' got me the whole string, where do I go from there?
If someone could answer all of the questions in the code I think that would probably be the best way of learning it since it's through example. Thanks!

Firstly, when you declare int* num, you created a pointer. You cannot assign a value directly to a pointer. What you could do is declare a variable, like you did for int x, and point the pointer to variable x (hence the name pointer) by using num = &x (&x refers to address of x, and is assigned to num) To get the value of num, you will have to use *num. Below is an example:
int *num;
int a = 4;
num = &a;
printf("address of a is %p, and value of a is %d", num, *num);
Output to first example:
address of a is <0xsome address> , and value of a is 4
As for characters, same thing you can't assign a value directly to pointer (like you did in char* word = "johnny";. A concept I think you should know is that "johnny" is a String, and strings are essentially an array of characters, hence each character of the string has its own address. Using similar to previous example:
char* word;
char someString[6] = "johnny";
word = &someString[0];
printf("address of first char of someString is %p, 1st char of someString is %c, 2nd char of someString is %c", word, *(word), *(word+1));
Output for the second example:
address of first char of someString is <0xsome address>, 1st char of someString is j, 2nd char of someString is o
Importing thing to note is that when accessing each character of the string using de-referencing of pointers, the +n must be inside the bracket with the pointer word.
*word+1 //WRONG
*(word+1) //CORRECT
Hope this gives you a base foundation of what you will need to tackle the rest of the questions!

Related

What is the difference between these access in C?

i started learning C today, and i have some questions about accessing a pointer data.
I have this function in C:
typedef struct
{
size_t size;
size_t usedSize;
char *array;
} charList;
void addToCharList(charList *list, char *data)
{
if(list->usedSize == list->size)
{
list->size *= 2;
list->array = realloc(list->array, list->size * sizeof(int));
}
list->array[list->usedSize++] = *data;
printf("1: %d\n", *data);
printf("2: %s\n", data);
printf("3: %p\n", &data);
}
I use it to create a "auto growing" array of chars, it works, but i'm not understanding why i need to attribute the value "*data" to my array. I did some tests, printing the different ways i tried to access the variable "data", and i had this outputs (I tested it with the string "test"):
1: 116
2: test
3: 0x7fff0e0baac0
1: Accessing the pointer (i think it's the pointer) gives me a number, that i don't know what is.
2: Just accessing the variable gives me the actual value of the string.
3: Accessing it using the "&" gets the memory location/address.
When i'm attributing the value of my array, i can only pass the pointer, why is that? Shouldn't i be attributing the actual value? Like in the second access.
And what is this number that gives me when i access the pointer? (First access)
So, in the first printf, you're not actually accessing the pointer. If you have a pointer named myPointer, writing *myPointer will actually give you access to the thing that the pointer is pointing to. It is understandable to be confused about this, as you do use the * operator when declaring a variable to specify that it is a pointer.
char* myCharPtr; // Here, the '*' means that myCharPtr is a pointer.
// Here, the '*' means that you are accessing the value that myCharPtr points to.
printf("%c\n", *myCharPtr);
In the second printf, you're accessing the pointer itself. And in the third printf, you're accessing a pointer to a char pointer. The & operator, when put before a variable, will return a pointer to that variable. So...
char myChar = 'c';
// pointerToMyChar points to myChar.
char* pointerToMyChar = &myChar;
// pointerToPointerToMyChar points to a pointer that is pointing at myChar.
char** pointerToPointerToMyChar = &pointerToMyChar;
When you're trying to store the value in the array, it's forcing you to do *data because the array stores chars, and data is a pointer to a char. So you need to access the char value that the pointer is pointing to. And you do that via *data.
Lastly: the reason that printf("1: %d\n", *data); prints a number is that chars are secretly (or not secretly) numbers. Every character has a corresponding numeric value, behind the scenes. You can see which numerical value corresponds to which character by looking at an ascii table.

How to get a string from a function which has a void pointer?

When I try to get a string from a function which has type void*, I only get the first character.
I tried to copy string manually without using strcpy() it gives me same problem
struct arr {
int first
int last.
void **val;
};
//I have a function which is called
void *inspect_arr(const arr *ar, int position)
{
....
return ar->val[offset];
}
//I want to inspect the array so that I can compare the strings
int main()
{
char *str = calloc(10,sizeof(char));
char *k = *(char*)inspect_arr(...) //I have a string in the array
// strcpy(str,k); Doesn't work
strcmp(str,k); Invalid read from valgrind
//If array has an integer type then I would write my code like this:
//int a = *(int*)inspect_arr(...) but I can not do the same thing for char
}
I get Segmentation fault when I run the program.
One problem is that first * in *(char*)inspect_arr(...).
There you dereference the pointer, getting only the first character. It's equivalent to ((char*)inspect_arr(...))[0].
To make it more troublesome, you then assign this single character to the pointer k. This doesn't make k point to the character, it make k point to whatever address corresponds to that characters encoded value. With e.g. ASCII and the character 'd' the initialization is equivalent to
char *k = 100;

Using memory adress from pointer to print character array (string) C

char mening[] = "tjena pa dig hog";
This string contains 16 characters. I am then using a function adresss() to find the memory address of a random character in that array. The function adresss() returns a pointer containing the address. The address is at this moment 0x7ffeefbff5f9.
I now need to know what positions that address is pointing to, example is it pointing to the "t" at position 0 in the array, or maybe it is pointing to "d" at position 9. How do I do this?
Edit:
char* adresss(char mening[]){
//Lots of code going on here
return &mening[i];
}
int main(void){
char mening[] = "tjena pa dig hog";
char* ptr;
ptr = adresss(mening);
printf("%p\n", ptr);
That is basically how I get the memory adress. I want to know what "i" was, inside the main function only knowing the memory adress.
If you have two pointers, both pointing to the same array (or to one beyond the end of the array), then you can subtract them from each other.
For example:
char mening[] = "tjena pa dig hog";
char *pointer_to_mening = &mening[10]; // Pointer to the eleventh character
// Should print 10 (which is the index of the eleventh character)
printf("The distance is %zu\n", pointer_to_mening - mening);

Confused about the printing procedure of array of pointers to string

#include<stdio.h>
int main(){
char *names[2] = {"Lord", "Voldemort"};
printf("%s %s\n",names[0], names[1]);
return 0;
}
Why is the above code working? I mean, it should print the addresses of the strings it is containing in their respective indexes and we should be using *names[0] and *names[1]. But why it is working though?
If you had an array of integers like
int values[2] = { 1, 2 };
then what would you get if use used e.g. values[1]? You would get the second element in the array. Printing this values array would be done like
printf("%d %d\n", values[0], values[1]);
You are with me this far?
Now back your array. If you use names[1] what do you get then? You still get the second element in the array. And what is the second element? It is a pointer to char (i.e. char *). And what can a pointer to char be used as? A string.
And the "%s" format with printf expects a string, a char * more specifically. Which is just what you give as arguments.
If you use the dereference operator like *names[1] then thanks to operator precedence it is equal to *(names[1]) which is equal to names[1][0]. In other words it gives you the first character in the string pointed to by names[1].
names[0] and names[1] are both const char* types.
When you use %s with a const char* argument, printf outputs the characters starting at the beginning of the argument, until \0 is reached.
If you want the addresses then use
printf("%p %p\n", (const void*)names[0], (const void*)names[1]);

Passing pointers to function

I have a doubt in my program
#include<stdio.h>
int myFunc(char **);
main()
{
char *a[2]={"Do","While"};
myFunc(a);
}
int myFunc(char **P)
{
/* Here I want to print the strings passed but I'm unable to
print the strings I just tried the below statement which
printed just the first letter which is 'D'*/
printf("%c",**P);
}
when i tried
printf("%s",**P);
I am getting run time error. so can anyone please help me out?
Thanks
Madhu
Put size as parameter to allow the function to know how many strings you have in your array. Then, you should iterate the array and print each one.
int myFunc( char** p, int size)
{
for( int i = 0; i < size; ++i)
{
printf("%s", p[i]);
}
}
Later edit (as requested :-) )
int main( int, char**)
{
char *a[2]={"Do","While"};
myFunc( a, 2); // Could be myFunc( a, sizeof(a)/sizeof(char*));
// ...
return 0;
}
Too many stars - try
printf("%s",*P);
And you need %s format specifier - %c is just for single character.
If you want to print all strings, you need to pass number of strings in array and then print these strings from the loop.
Check the code suggested by Cătălin Pitiș. To pass the number of strings, you call function like this:
myFunc(a, sizeof(a)/sizeof(a[0]));
for( int i = 0; i < 2; i++ ) {
char* string = P[i];
printf( "%s", string );
}
And you shoud use some way of passing size of array into the function - either pass it as an int parameter,
int myFunc(char **P, int size)
{
for( int i = 0; i < size; i++ ) {
//whatever here
}
}
or always append a zero value to the array and only loop until you find that zero value.
char* array[] = { "String1", "String2", 0 };
Otherwise you will have hard to maintain code.
I like objective-c style nil (0) terminated arrays:
void myFunc(char **P)
{
while (*P) // loop to iterate over all strings until 0
printf("%s\n",*P++); // print and move to next element in array
}
int main()
{
char *a[]={"Do","While",0}; // added 0 to null terminate array,
myFunc(a); // kind of like string
}
Output:
Do
While
First, the good news: the type of a is equivalent to char **, so you are passing a valid parameter to myFunc().
The first problem is that %c is a format specifier that means print a single character. Since **P is an expression that evaluates to a single character, your first version does exactly what you told it to do. That isn't what you want.
The second version is close to syntactically correct. It should read printf("%s", *P), where *P is an expression that evaluates to a pointer to a nul-terminated ASCII string. In this case, it evaluates to "Do". This version won't print both strings.
Although it is true that the name of an array is the same as a pointer to its first element, that is a kind of "lie to students". Passing an array to a function does not and cannot convey the length of the array. To do that, you need either a second argument containing the length, or a convention like the nul-terminator on a string to indicate the end of the array. With that change, you can modify myFunc() to use a loop over the elements passed and print each one.
The problem in your code is that you want to print a string (char*) but you're giving it a char. Remember that P is an array of char*. When you de-reference it once, you get a char*; when you do it a second time, you just get the char at the beginning of the char*.
When you try to use the char value with the %s specifier, it treats the value as a pointer, and tries to dereference that value. Hence, it will try to print the "string" at the memory location X, where X is the value of the char (i.e. a value from 0 to 255). This gives you an access violation/segmentation fault (the error you see at runtime).
The best workarounds for this, as noted by Cătălin Pitiș and RBerteig, are to either:
pass another parameter to specify the length of the array
add an additional null at the end of the array.
if you don't want to keep and pass around array size::
int myFunc(char **);
main()
{
char *a[2]={"Do","While", NULL};
myFunc(a);
}
int myFunc(char **P)
{
if( !P )
return 0;
while(*P != NULL)
{
printf("%s",*P);
P++;
}
}
Wrong Answer: I think you may have to dereference P when you print it, although I could be wrong.
EDIT: I'm tired, it's 3 am here but I don't feel like sleeping so I'm here trying to answer questions. After reading the criticism, I reread the question and noticed that he does dereference P, but as is stated in another answer, it's dereferenced too much. When one wants to print a char string, one wants to pass a pointer as the char string is really an array.
Another EDIT: I would also like to point out that the person who asked the question made an edit after I answered and that when I first answered it didn't read "printf("%s",**P);" it read "printf("%s", P);" and the last part was bold.

Resources