Gaining acces to an element using pointers - c

I'm doing a C quiz on the internet and came across the following question :
How to write a[i][j][k][l] using only pointers, I know that a[i] can be written as *(a+i), but further than that I don't know.

As you stated, a[i] can be written as *(a+i), using this principle a[i][j] == *(*(a+i)+j)
a[i][j][k] == *(*(*(a+i)+j)+k) and finally a[i][j][k][l] == *(*(*(*(a+i)+j)+k)+l), I know it looks odd but that's how it's done( I think I did the same quiz recently )

You are using "only pointers". a[i] is defined only when either a or i is a pointer or is converted to one. *(a + i) is exactly equivalent to a[i] and *(i + a) and i[a].
It can be written as *(*(*(*(a + i)+j)+k)+l) or for example *(l + *(k + *(*(a + i) + j))) for example, but this is not "using pointers" any more than a[i][j][k][l].
I'd avoid such a quiz like plague and redirect the entire host that serves such garbage to localhost.

Related

How does the C expression s[i ++] = t[j ++] exactly work in order?

I'm new in C, stuck in understanding the expression s[i ++] = t[j ++], I don't know how it's possible that an array element gets accessed with a variable and then the variable increase itself and then the array element just accessed is again accessed with the original variable and then gets assigned to another array's element, I'm confused, I think to understand the exact process might involve some low-level knowledges, but I don't want to digress too far away, is there any way to understand it easily and clearly?
In C language, the expression i++ causes i to be incremented, but the expression i++ itself evaluates to the value i had before being incremented. So the expression s[i++] = t[j++] has the same behaviour as:
s[i] = t[j];
i = i + 1;
j = j + 1;
except that the precise order is not specified. For that last reason, the rule is that a variable should only be modified once: s[i++] = t[i++] would invoke Undefined Behaviour.
Like any other complicated-looking expression, it's easier to understand this if you break it down into parts.
The key is that innermost part (or "subexpression") i++. I assume you know what i++ does by itself, although in this example, we're hopefully going to get a deeper appreciation of what i++ is actually good for. Why would you want to "increment i, but return the old value"? What's the use of this? Well, the main use is that it's super useful for moving along an array.
Lets look at a simpler example. Suppose we have an array a that we want to store some numbers in. The most basic way is
int a[10];
a[0] = 12;
a[1] = 34;
a[2] = 5678;
Another very good way is to use a second variable like i to keep track of where we're storing:
i = 0;
a[i] = 12;
i = i + 1;
a[i] = 34;
i = i + 1;
a[i] = 5678;
i = i + 1;
I've written this out in "longhand", but of course in C, you would almost never write it this way, because the "C way" is the much more concise
i = 0;
a[i++] = 12;
a[i++] = 34;
a[i++] = 5678;
So first, make sure you understand that the "shorthand" and "longhand" forms work exactly the same way. Make sure you understand that when we say something like
a[i++] = 34;
what this means is "store 34 into the slot in array a indicated by i, and then update i to be one more than is used to be, so that it indicates the next slot."
In other words, we use an expression like a[i++] whenever we want to move along an array and do something with its elements, one by one, in order.
So far we were storing values into the array, but the idiom works just as well for fetching values out of an array. For example, this code prints those three elements, again one at a time, in order:
i = 0;
printf("%d\n", a[i++]);
printf("%d\n", a[i++]);
printf("%d\n", a[i++]);
My point is, again, that any time you see an expression like a[i++], you should think "we're moving along the array".
So now, finally, we can look at the expression you initially asked about:
s[i++] = t[j++];
Here we have two instances of the idiom. We're using i to move along the array s, and we're using j to move along the array t. We're fetching from t as we move along, and we're storing the values into s.
I don't know whether s and t are arrays of characters, or integers, or what. Also I don't know that s and t are truly arrays -- they might actually be pointers, pointing into some arrays. But I don't really have to know those things to know that the essential meaning of s[i++] = t[j++] is "copy elements from array t to array s, using j to keep where we are in t, and i to keep track of where we are in s".
[The above is an answer to your original question. The rest of this answer isn't directly related, but is essential to avoid inadvertently writing incorrect programs using ++ and --.]
As I said, the subexpression i++ and the idiom a[i++] are super useful for moving through arrays. But there are a couple things to beware of. (Actually it's just one thing, but it crops up in lots of different ways.)
Earlier I wrote the code
i = 0;
printf("%d\n", a[i++]);
printf("%d\n", a[i++]);
printf("%d\n", a[i++]);
to print the first three elements of the array a. But it prints them as bare, isolated numbers. What if I want to always see which array index each number comes from? That is, what if I'm tempted to write something like this:
i = 0;
printf("%d: %d\n", i, a[i++]); /* WRONG */
printf("%d: %d\n", i, a[i++]); /* WRONG */
printf("%d: %d\n", i, a[i++]); /* WRONG */
If I wrote this, my intent would be that I would see the obvious display
0: 12
1: 34
2: 56788
But when I actually tried it just now, I got this instead:
1: 12
2: 34
3: 5678
The numbers 12 and 34 and 5678 are right, but the indices 1, 2, and 3 are all wrong -- they're off by one! How did that happen?
And the answer is that although i++ is, as I said, "super useful", it turns out that there's a fine line between "super useful" and what's called undefined behavior.
That printf call
printf("%d: %d\n", i, a[i++]); /* WRONG */
looks fine, but it's not actually well-defined, because the compiler does not necessarily evaluate everything left-to-right, so it's not actually guaranteed that it will use the old value of i for the %d: part. The compiler might evaluate things from right to left, meaning that a[i++] will happen first, meaning that %d: will print the new value, instead -- which appears to be what happened when I tried it.
Here's another potential issue. Your original question was about
s[i++] = t[j++];
which, as we've seen, copies elements from t to s based on two possibly-different indices i and j. But what if we know we always want to copy t[1] to s[1], t[2] to s[2], t[3] to s[3], etc.? That is, what if we know that i and j will always be the same, so we don't even need separate i and j variables? How would we write that? Our first try might be
s[i++] = t[i++]; /* WRONG */
but that can't be right, because now we're incrementing i twice, and we'll probably do something totally broken like copying t[1] to s[2] and t[3] to s[4]. But if we want to only increment i once, should it be
s[i++] = t[i]; /* WRONG */
or
s[i] = t[i++]; /* WRONG */
But the answer is that neither of these will work. In expressions like these, which have i in one place and i++ in the other place, there's no way to tell whether i gets the old value or the new value. (In particular, there's no left-to-right or right-to-left rule that would tell us.)
So although expressions like i++ and a[i++] are indeed super useful, you have to be careful when you use them, to make sure you don't go over the edge and have too much happening at once, such that the evaluation order becomes undefined. Sometimes this means you have to back off, and not use the "super useful" idiom, after all. For example, a safe way to print those values would be
printf("%d: %d\n", i, a[i]); i++;
printf("%d: %d\n", i, a[i]); i++;
printf("%d: %d\n", i, a[i]); i++;
and a safe way to copy from t[1] to s[i] would be
s[i] = t[i]; i++;
You can read more in this answer about how to recognize well-defined expressions involving ++ and --, and how to avoid the undefined ones.
The evaluations of s[i++] and t[j++] are unsequenced relative to each other. Semantically, it's equivalent to:
t1 = i;
t2 = j;
s[t1] = t[t2];
i = i + 1;
j = j + 1;
with the caveat that the last three assignments can happen in any order, even simultaneously (either in parallel or interleaved)1. The compiler doesn't have to create temporaries, either - the whole thing can be evaluated as
s[i] = t[j];
i = i + 1;
j = j + 1;
Alternately, the side effects of i++ and j++ can be applied before the update to s:
t1 = j;
j = j + 1;
t2 = i;
i = i + 1;
s[t2] = t[t1];
The current values of i and j must be known before you can index into the arrays, and the value of t[j] must be known before it can be assigned to s[i], but beyond that there's no fixed order of evaluation or of the application of side effects.
This is why expressions like x = x++ or a = b++ * b++ or a[i] = i++ all invoke undefined behavior - there's no fixed order for evaluating or applying side effects, so the results can vary by compiler, compiler settings, even by the surrounding code, and the results don't have to be consistent from run to run.

Can't understand &(sizeof 2[a])[a]

I've got some code that outputs bcdefg and I can't understand why.
I google searched but I couldn't find anything.
const char a[]="Abcdefg";
printf("%s",&(sizeof 2[a])[a]);
Why is the output bcdefg, and not Abcdefg?
This code is meant to confuse you, not do anything useful. Don't write code like this. Here is how it is interpreted by the compiler:
2[a] is the same as a[2], which is a value of char type (which value exactly doesn't matter; the compiler even doesn't try to evaluate it)
sizeof 2[a] is the same as sizeof(char), which is equal to 1
&(sizeof 2[a])[a] is a pointer to the character b in the string Abcdef - the one which has the index 1
printf("%s",&(sizeof 2[a])[a]) prints the string, starting at that pointer
Referring to the code excerpt:
printf("%s",&(sizeof 2[a])[a]);
First, most people don't realize it, but the [] operator it actually commutative. a[b] is equivalent to *(a + b), which is equivalent to *(b + a), which is equivalent to b[a].
So 2[a] is equivalent to a[2]. Since a has type const char [], the size of an element is the same as sizeof(char), which is 1.
So we now have:
printf("%s",&1[a]);
Well, 1[a] is equivalent to a[1], or *(a + 1). Applying the address-of operator gives &a[1], or a + 1 (note that &*x is just x).
So we have:
printf("%s", a + 1);
This just prints the string pointed to by a + 1, i.e. everything after the first character of a.
If you just reorder the [] operators without doing anything else, you can see that it's equivalent to:
printf("%s", &a[sizeof a[2]]);
If you break down each segment:
&(sizeof 2[a])[a]
2[a] = a[2]. a[2] = a char element at position 2
sizeof(char) = 1
(1)[a] = a[1]
&(a[1]) = a reference to the 'b' in "bcdefg"
printf() then prints the char array starting with b and ending at the null terminator

Weird C Syntax 1["ABCDE"]?

Can anyone please help me understand the following code:
int d = 4;
printf(&d["Hay!Hello %c\n"], &4["BuddyWorld"]); // Hello (some address in char)
printf(&d["Hay!Hello %c\n"], 4["BuddyWorld"]); // Hello y
printf(&d["Hay!Hello %s\n"], 4["BuddyWorld"]); // Segmentation fault
printf(&d["Hay!Hello %s\n"], &4["BuddyWorld"]); // Hello yWorld
printf("d[Hay!Hello %s\n"], &4["BuddyWorld"]);
/* warning: passing argument 1 of 'printf' makes pointer
from integer without a cast */
What is exactly the d[] or &d[] operator? (d is an integer)
Why does &4["BuddyWorld"] and 4[BuddyWorld] yields to different values? ('W' and 'y' respectively)
When you write something like a[i], it gets expanded into *(a + i). (We say a[i] is syntactic sugar for *(a + i)).
Addition is commutative, so "BuddyWorld"[4] = *("BuddyWorld" + 4) = *(4 + "BuddyWorld") = 4["BuddyWorld"], where "BuddyWorld" implicitly stands for its address in memory.
Subscripting in C is weird. a[b] is turned into *(a + b) (the thing at the address obtained by adding b to the pointer a). However, since a + b == b + a, it works the other way around as well (a[b] == b[a]). That's all that's going on. In particular, "HelloWorld" is really a pointer to a character array that stores the characters of the string.
d["Hay!Hello %c\n"] is the same as "Hay!Hello %c\n"[d].
And the & operator gives the address of the pointed content

Accessing the results array from sqlite3_get_table

I'm using Ansi C and sqlite3_get_table; everything works except I can't access the query results vector passed as a pointer to an array. Here's my code...
char **sql_results;
sqlite3_get_table(open_database, sql_query,
&sql_results, &RecordCount, &ColumnCount, &error_msg);
for (int i = 0; i <= (RecordCount + 1)* (ColumnCount); i++)
printf("%10d %10s\n",i, sql_results[i]); //get "EXC BAD ACCESS" message
How do I fix sql_results[i]? Thanks.
I think this piece:
i <= (RecordCount + 1)* (ColumnCount)
is causing you the problems. Did you also try
i < (RecordCount + 1)* (ColumnCount)
You should check that the value returned by sqlite3_get_table is SQLITE_OK; it's not safe to access the result table if it isn't.
You should also be aware that this is a deprecated API. And you should add a call to sqlite3_free_table to release the memory; right now you appear to have a memory leak (or you've already done that, but declined to show us).

Different way of accessing array elements in C

I am a teaching assistant for a C programming course, and I came across the following line of C code:
char str[] = "My cat's name is Wiggles.";
printf("%c %c %c %c\n", str[5], *(str + 5), *(5 + str), 5[str]);
I never came across the very last argument (5[str]) before, and neither did my professor. I don't think it's mentioned in K&R and C Primer Plus. I found this piece of code in a set of technical interview questions. Does anyone know why C allows you to access an array element that way also? I never heard of an index being outside the set of brackets and the name of an array inside the brackets.
Your help will be greatly appreciated!
Perfectly valid C. From Wikipedia:
Similarly, since the expression a[i] is semantically equivalent to *(a+i), which in turn is equivalent to *(i+a), the expression can also be written as i[a] (although this form is rarely used).
Wacky, but valid.
str[5] directly translates to *(str + 5), and 5[str] directly translates to *(5 + str). Same thing =)
It's basically just the way C works. str[5] is really equivelent to *(str + 5). Since str + 5 and 5 + str are the same, this means that you can also do *(5 + str), or 5[str].
It helps if you don't think of "5" as an index, but rather just that addition in C is commutative.
Similarly, since the expression a[i] is semantically equivalent to *(a+i), which in turn is equivalent to *(i+a), the expression can also be written as i[a] (although this form is rarely used).
http://en.wikipedia.org/wiki/C_syntax#Accessing_elements
Its all same. *ptr or ptr[0] actually means *(ptr+0). So whenever you write *ptr or ptr[0] it goes as *(ptr+0). Let say you want value at ptr[4] so it means you can also write it as *(ptr+4). Now whether you write it as *(ptr+4) or *(4+ptr), it's same. so just for understading if you can write *(ptr+4) as ptr[4] same way *(4+ptr) is same as 4[ptr]. Please go through http://en.wikipedia.org/wiki/C_syntax#Accessing_elements for more details.
if str is an array of type char, then we can access any index say i as below-
str[i]
*(str + i)
char *p = str, then access the index i as p[i] or *(p+i)
It's a funky syntax for sure, but...
str[5] would mean *(str+5)
And
5[str] would mean *(5+str)
Example Code.
#include<stdio.h>
int main(){
int arr[] = {1, 2, 3};
for(int i = 0; i <= 2; i++){
printf("%d\t", i[arr]);
}
return 0;
}
Output:1 2 3

Resources