Pointer dereferencing in a variable and in an array in C [closed] - c

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I am somewhat confused on pointers. I have two of them in the following code I'm using and they are working but I'm not 100% sure why they are working.
The first is
char *note = "A7";
The second is
char *octFreq[15] =
{"1","55","2","110","3","220","4","440","5","880","6","1760","7","3520"};
They both get to the value of each though I had to use * before the array and not before the single variable. I am able to get the value of note by just using note though cannot do this for octFreq.
Here is the line of code I'm a little confused by and all of the code immediately follows.
if(note[1] == *octFreq[x]){//WHY DO I HAVE TO DEREFERENCE octFreq and not note????
#include <stdio.h>
#include <cs50.h>
#include <stdbool.h>
#include <string.h>
int main(void){ //Notes are in this order C D E F G A B
char *note = "A7";
//char freq;
int semiUpDown = 0;
char *octFreq[15] = {"1","55","2","110","3","220","4","440","5","880","6","1760","7","3520"};
//int noteIndex[7] = {1, 2, 3, 4, 5, 6};
if(note[1] == '#'){
semiUpDown = 1;
//Up one semitone or multipled by 2^1/12
}else if(note[1] == 'b'){
semiUpDown = -1;
//Down one semitone or divide by 2^1/12
}
if(semiUpDown == 0){//This means no flat or sharp
if(note[0] != 'B' || note[0] != 'b'){//Check the first letter is CDEFGA
if(note[0] == 'A' || note[0] == 'a'){//Check to see if it's the baseline
for(int x = 0; x < 13; x++){
//printf("%s\n\n", noteA[x]);
if(note[1] == *octFreq[x]){//WHY DO I HAVE TO DEREFERENCE octFreq and not note????
//freq = *octFreq[x+1];
// printf("Found it: %s\n\n", noteA[x]);
printf("This is the frequency: %s\n\n", octFreq[x+1]);
}
}
}
}
}
}

char *note = "A7" means that you have declared a pointer to a char array. Therefore you can access its elements by note[0] etc. like any other array.
char *octFreq[15] means that you declared a pointer to an array of char pointers.
octFreq[15] would reach to the char pointer at the index 15.
*octFreq[15] would reach to the char pointed by the char pointer at the index 15.

if(note[1] == *octFreq[x]) is only comparing a single character so it works for A7 but won't work for A110. There you need to use strcmp which uses char * to compare entire strings. Something like this;
if (0 == strcmp(&note[1], octFreq[x]))

The index operator ([]) is an automatic dereference of a specific integer amount from the base pointer value.
So, to explain. A pointer is really just a variable that holds a memory location. This memory location is a specific integer value (i.e. 4000, 9320, etc.). You can add, subtract, multiply, divide, etc., this variable to get a new memory location that points to a valid value of the type the pointer points to (in this case, a char).
Your first pointer variable, note, could be defined as such:
char* note = new char[3];
*(note + 0) = 'A';
*(note + 1) = 'F';
*(note + 2) = '\0'; \\all character arrays have an implicit null-terminator
Each character can be then referenced as: note[x], where 0 <= x <= 2. note[x] can also be read as *(note + x).

char* note = "A7"; // here you define note - array of chars ('A', '7', '\0'). When you access note[1], you get the second symbol ('7').
char* octFreq[15] = {"1","55","2","110","3","220","4","440","5","880","6","1760","7","3520"}; // here you define octFreq - array of arrays of char. There are 15 arrays, were every has type char*. So when you access octFreq[3], you getting the fourth element of array of arrays of char and it is array of chars ("110" in this example). Then you apply * to this array of chars and you get the first element of this array (it is bold one here -> "110"), because the pointer to array of chars (char*) actually points to it's first element.

Related

Do arrays end with NULL in C programming?

I am a beginner to C and I was asked to calculate size of an array without using sizeof operator. So I tried out this code, but it only works for odd number of elements. Do all arrays end with NULL just like string.
#include <stdio.h>
void main()
{
int a[] = {1,2,3,4,5,6,7,8,9};
int size = 0;
for (int i = 0; a[i] != '\0'; i++)
{
size++;
}
printf("size=%d\n", size);
}
No, in general, there is no default sentinel character for arrays.
As a special case, the arrays which ends with a null terminator (ASCII value 0), is called a string. However, that's a special case, and not the standard.
> So I tried out this code, but it only works for odd number of elements.
Try your code with this array -
int a[] = {1,2,0,4,5,6,7,8,9};
^
|
3 replaced with 0
and you will find the output will be size=2, why?
Because of the for loop condition - a[i] != '\0'.
So, what's happening when for loop condition hit - a[i] != '\0'?
This '\0' is integer character constant and its type is int. It is same as 0. When a[i] is 0, the condition becomes false and loop exits.
In your program, none of the element of array a has value 0 and for loop keep on iterating as the condition results in true for every element of array and your program end up accessing array beyond its size and this lead to undefined behaviour.
> Do all arrays end with NULL just like string.
The answer is NO. In C language, neither array nor string end with NULL, rather, strings are actually one-dimensional array of characters terminated by and including the first null character '\0'.
To calculate size of array without using sizeof, what you need is total number of bytes consumed by array and size (in bytes) of type of elements of array. Once you have this information, you can simply divide the total number of bytes by size of an element of array.
#include <stdio.h>
#include <stddef.h>
int main (void) {
int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
ptrdiff_t size = ((char *)(&a + 1) - (char *)&a) / ((char *)(a + 1) - (char *)a);
printf("size = %td\n", size);
return 0;
}
Output:
# ./a.out
size = 9
Additional:
'\0' and NULL are not same.

in C, why do I have " "s": initialization requires a brace-enclosed initializer list"?

DISCLAIMER: it's just a piece of the whole algorithm, but since I encountered a lot of errors, I've decided to divide and conquer, therefore, I start with the following code. (goal of the following code: create a string with the remainders of the division by 10 (n%10). for now, it's not reversed, I haven't done it yet, because I wanted to check this code first).
(i'm working in C, in visual studio environment).
I have to implement a function like atoi (that works from a string to a number), but I want to do the opposite (from a number to a string). but I have a problem:
the debugger pointed out that in the lines with the malloc, I should have initialized the string first (initialization requires a brace-enclosed initializer list),
but I have done it, I have initialized the string to a constant (in the 2nd line, I've written "this is the test seed")(because I need to work with a string, so I initialized, and then I malloc it to write the values of (unsigned int n) ).
this is how my program is supposed to work:
(1) the function takes an unsigned int constant (n),
(2) the function creates a "prototype" of the array (the zero-terminated string),
(3) then, I've created a for-loop without a check condition because I added it inside the loop body,
(4) now, the basic idea is that: each step, the loop uses the i to allocate 1 sizeof(char) (so 1 position) to store the i-th remainder of the n/10 division. n takes different values every steps ( n/=10; // so n assumes the value of the division). and if n/10 is equal to zero, that means I have reached the end of the loop because each remainder is in the string). Therefore, I put a break statement, in order to go outside the for-loop.
finally, the function is supposed to return the pointer to the 0-th position of the string.
so, to sum up: my main question is:
why do I have " "s": initialization requires a brace-enclosed initializer list"? (debugger repeated it twice). that's not how string is supposed to be initialized (with curly braces "{}"). String is initialized with " " instead, am I wrong?
char* convert(unsigned int n) {
char s[] = "this is the test seed";
for (unsigned int i = 0; ; i++) {
if (i == 0) {
char s[] = malloc (1 * sizeof(char));
}
if (i != 0) {
char s[] = malloc(i * sizeof(char));
}
if ((n / 10) == 0) {
break;
}
s[i] = n % 10;
n /= 10;
}
return s;
}
char s[]is an array, and therefore needs a brace-enclosed initializer list (or a character string literal). In the C standard, see section 6.7.8 (with 6.7.8.14 being the additional special case of a literal string for an array of character type). char s[] = malloc(...); is neither a brace-enclosed initializer list or a literal string, and the compiler is correctly reporting that as an error.
The reason for this, is that char s[] = ...; declares an array, which means that the compiler needs to know the length of the array at compile-time.
Perhaps you want char *s = malloc(...) instead, since scalars (for example, pointers) can be initialized with an assignment statement (see section 6.7.8.11).
Unrelated to your actual question, the code you've written is flawed, since you're returning the value of a local array (the first s). To avoid memory problems when you're coding, avoid mixing stack-allocated memory, statically allocated strings (eg: literal strings), and malloc-ed memory. If you mix these together, you'll never know what you can or can't do with the memory (for example, you won't be sure if you need to free the memory or not).
A complete working example:
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
char *convert(unsigned n) {
// Count digits of n (including edge-case when n=0).
int len = 0;
for (unsigned m=n; len == 0 || m; m /= 10) {
++len;
}
// Allocate and null-terminate the string.
char *s = malloc(len+1);
if (!s) return s;
s[len] = '\0';
// Assign digits to our memory, lowest on the right.
while (len > 0) {
s[--len] = '0' + n % 10;
n /= 10;
}
return s;
}
int main(int argc, char **argv) {
unsigned examples[] = {0, 1, 3, 9, 10, 100, 123, 1000000, 44465656, UINT_MAX};
for (int i = 0; i < sizeof(examples) / sizeof(*examples); ++i) {
char *s = convert(examples[i]);
if (!s) {
return 2;
}
printf("example %d: %u -> %s\n", i, examples[i], s);
free(s);
}
return 0;
}
It can be run like this (note the very useful -fsanitize options, which are invaluable especially if you're beginning programming in C).
$ gcc -fsanitize=address -fsanitize=leak -fsanitize=undefined -o convert -Wall convert.c && ./convert
example 0: 0 -> 0
example 1: 1 -> 1
example 2: 3 -> 3
example 3: 9 -> 9
example 4: 10 -> 10
example 5: 100 -> 100
example 6: 123 -> 123
example 7: 1000000 -> 1000000
example 8: 44465656 -> 44465656
example 9: 4294967295 -> 4294967295

Looking at and using individual bytes in void pointers in C [duplicate]

This question already has answers here:
What does void* mean and how to use it?
(10 answers)
Closed 5 years ago.
I'm trying to make a calculator that takes a void pointer called yourVal, look at the first byte and decide if it's a '*' or '/'. Based on the sign, i multiply bytes 3+4, 5+6, and 7+8. say i have *1234567. I multiply 23 * 45 * 67. With the division, I divide byte 5(45) by byte 3(23). I'm a novice with pointers in C, and I really have no idea how to even set a value to a void pointer. When I do the following in main
void *yourVal;
*yourVal = "*1234567";
printf("%s\n", yourVal);
I'm not able to dereference a void pointer. But I tried with a char pointer, and I have the same issue.
This is my code for the calculator function. Based on whether I use printf or not, I get different results.
int calculator(void *yourVal){
char *byteOne;
short int *byteThree, *byteFive, *byteSeven;
int value;
byteOne = (char *)yourVal;
byteThree = (short int *)yourVal+2;
byteFive = (short int *)yourVal+4;
byteSeven= (short int *)yourVal+6;
if(*byteOne == '*') {
value = *byteThree * *byteFive * *byteSeven;
printf("You multiplied\n");
}
else if(*byteOne == '/') {
if (*byteThree == 0) {
value = 0xBAD;
printf("Your input is invalid\n");
}
else {
value = *byteFive / *byteThree;
printf("You divided\n");
}
}
else {
value = 0xBAD;
printf("Your input is invalid\n");
}
}
The division isn't working at all, and the multiplication only grabs one digit. Any tips would be appreciated. I looked at various sources but I'm not seeing how to work with void pointers efficiently. Also, I can't use any library functions other than printf, and this is a school assignment, so try not to give too many spoilers or do it for me. We were given one hint, which is to cast yourVal to a structure. But I'm lost on that. Thanks
byteOne = (char *)payload;
byteThree = (short int *)yourVal+2;
byteFive = (short int *)yourVal+4;
byteSeven= (short int *)yourVal+6;
This doesn't do what you think it does. If you want to read the numbers at these positions, you need to do something like.
char* Value = yourValue;
unsigned byteOne, byteThree, byteFive, byteSeven;
byteOne = Value[0] - '0';
byteThree = Value[2] - '0';
byteFive = Value[4] - '0';
byteSeven = Value[6] - '0';
What I have done here is read the byte at that position and subtract the ASCII value of '0' to get the numerical value of that character. But again this will work only for a single character.
If you need to read more characters you will have to use library functions like sscanf or atoi.
The void pointer adds no functionality you need to solve this problem, it just complicates things. Use a char pointer instead.
"*1234567" is a string, not an array of integers. You cannot treat it as an array of integers. Each character would have to be converted to an integer before you do arithmetic. The easiest way to do that is to subtract by the ASCII character '0'.
"...i multiply bytes 3+4..." When counting bytes, you always start at 0. In the string "*1234567", the 2 is the byte with index 2 not 3.
"Based on the sign, i multiply bytes 3+4, 5+6, and 7+8. say i have *1234567. I multiply 23 * 45 * 67. With the division, I divide byte 5(45) by byte 3(23)"
I fail to see how this algorithm makes any sense. What is the 1 there for? Why aren't you using some conventional formatting such as prefix, postfix or just plainly typed-out equations?
Example:
int calculator (const char* yourVal)
...
int byte2 = yourVal[2] - '0';

Trying to print form array or array addresses...not getting it?

new here, trying to learn a piece of C with the great help of you guys, this could be a basic questions here....sorry you have start from basic.
void main()
{
char* arr[3] = {"baba","tata","kaka"};
char* arr1[3] = {"baba1","tata1","kaka1"};
char* arr2[3] = {"baba2","tata2","kaka2"};
char** array_all[] = {arr,arr1,arr2};
printf("%s\n",*array_all[0]);
//please guide me how to access individual entity(as arr[1], arr1[2],arr3[1]) //from each array using array_all
}
I'm not sure if this is exactly what you were looking for.. but this is what I understand so far.
You are wanting to access the individual elements of array_all (the elements arr, arr1 and arr2)? If so then all you do is...
array_all[0][i];
Where i is the element that you want to access.
The reason for this is because the index operators ([ and ]) actually dereferences a pointer and offsets the pointer (as in adds it by some integer, i.e. you move down in memory) that you specify. I recommend reading up on pointer arithmetic if you have no clue what happens if you add a pointer by some integer.
For example:
int x[] = { 1, 2, 3 };
// writing x[i] is the same as *(x + i)
int i = 2; // the element you wish to access
*(x + i) = 4; // set the ith (3rd) element to 4
*(x + 1) = 43; // set the 2nd element to 43
// Therefore...
// x now stores these elements:
// 1, 43, 4
// proof: print out all the elements in the array
for(int i = 0; i < 3; ++i)
{
printf("x[%i]=%i\n", i, x[i]);
}
Also, writing x[0] is the same as writing *x, since the array name actually points to the first element of the array.
OH and one thing, main should actually return an integer result. This is mainly used for error checking in your program, 0 usually means no error occurred and every other error-code (number other than 0) is some specific error related to your program, that you can choose.
i.e.
int main()
{
// e.g. for an error code
/*
if(someErrorOccured)
{
return SOME_ERROR_OCCURED_RETURN_VALUE;
}
*/
return 0; // this is at the end of the function, 0 means no error occured
}
change your printf statement line with this..
printf("%s\n",array_all[i][j]);
In place of i keep your array number and in place of k give your required element number. It works.

Why are the elements in my char* array two bytes instead of four? :

I am new to C, so forgive me if this question is trivial. I am trying to reverse a string, in
my case the letters a,b,c,d. I place the characters in a char* array, and declare a buffer
which will hold the characters in the opposite order, d,c,b,a. I achieve this result using
pointer arithmetic, but to my understanding each element in a char* array is 4 bytes, so when I do the following: buffer[i] = *(char**)letters + 4; I am supposed to be pointing at the
second element in the array. Instead of pointing to the second element, it points to the third. After further examination I figured that if I increment the base pointer by two
each time I would get the desired results. Does this mean that each element in the array
is two bytes instead of 4? Here is the rest of my code:
#include <stdio.h>
int main(void)
{
char *letters[] = {"a","b","c","d"};
char *buffer[4];
int i, add = 6;
for( i = 0 ; i < 4 ; i++ )
{
buffer[i] = *(char**)letters + add;
add -= 2;
}
printf("The alphabet: ");
for(i = 0; i < 4; i++)
{
printf("%s",letters[i]);
}
printf("\n");
printf("The alphabet in reverse: ");
for(i = 0; i < 4; i++)
{
printf("%s",buffer[i]);
}
printf("\n");
}
You're not making an array of characters: you're making an array of character strings -- i.e., an array of pointers to arrays of characters. I am not going to rewrite the whole program for you of course, but I'll start out with two alternative possible correct declarations for your main data structure:
char letters[] = {'a','b','c','d, 0};
char * letters = "abcd";
Either of these declares an array of five characters: a, b, c, d followed by 0, the traditional ending for a character string in C.
Another thing: rather than making assumptions about the size of things, use the language to tell you. For instance:
char *my_array[] = { "foo" , "bar" , "baz" , "bat" , } ;
// the size of an element of my_array
size_t my_array_element_size = sizeof(my_array[0]) ;
size_t alt_element_size = size(*my_array) ; // arrays are pointers under the hood
// the number of elements in my_array
size_t my_array_element_cnt = sizeof(my_array) / sizeof(*myarray ;
// the size of a char
size_t char_size = sizeof(*(my_array[0])) ; // size of a char
Another thing: understand your data structures (as noted above). You talk about chars, but your data structures are talking about strings. Your declarations:
char *letters[] = {"a","b","c","d"};
char *buffer[4];
get parsed as follows:
letters is an array of pointers to char (which happen to be nul-terminated C-style strings), and it's initialized with 4 elements.
Like letters, buffer is an array of 4 pointers to char, but uninitialized.
You are not actually dealing individual chars anywhere, even in the printf() statements: the %s specifier says the argument is a nul-terminated string. Rather, you're dealing with strings (aka pointers to char) and arrays of the same.
An easier way:
#include <stdio.h>
int main(void)
{
char *letters[] = { "a" , "b" , "c" , "d" , } ;
size_t letter_cnt = size(letters)/sizeof(*letters) ;
char *buffer[sizeof(letters)/sizeof(*letters)] ;
for ( int i=0 , j=letter_cnt ; i < letter_cnt ; ++i )
{
buffer[--j] = letters[i] ;
}
printf("The alphabet: ");
for( int i = 0 ; i < letter_cnt ; ++i )
{
printf("%s",letters[i]);
}
printf("\n");
printf("The alphabet in reverse: ");
for( int i=0 ; i < letter_cnt ; i++ )
{
printf("%s",buffer[i]);
}
printf("\n");
}
BTW, is this homework?
This is a case of operator precedence. When you use buffer[i] = *(char**)letters + add;, the * before the cast is performed before the +, making this code equivalent to (*(char**)letters) + add;. The first part is equivalent to the address of the first element in your array, the string "a". Since using string constant automatically adds a null byte, this points to 'a\0'. It happens that the compiler placed all four strings immediately after each other in memory, so if you go past the end of that string you flow into the next. When you add to the pointer, you are moving through this character array: 'a\0b\0c\0d\0'. Notice that each character is 2 bytes after the last. Since this is only true because the compiler placed the 4 strings directly after each other, you should never depend on it (it won't even work if you tried to re-reverse your other string). Instead, you need to put in parentheses to make sure the addition happens before the dereference, and use the 4 byte pointer size. (Of course, as pointed out by Nicholas, you shouldn't assume the size of anything. Use sizeof to get the size of a pointer instead.)
buffer[i] = *((char**)letters + add);
char *letters[] = {"a","b","c","d"};
I think you didn't get the pointer arithmetic correctly. letters is an array of pointers and when incremented by 1 makes to go to next row.
letters + 1 ; // Go to starting location of 2 row, i.e., &"b"
char *letters[] = { "abc" , "def" } ;
(letters + 1) ; // Point to the second row's first element, i.e., &"d"
*((*letters) + 1) ; // Get the second element of the first row. i.e., "b"

Resources