// Capitalizes a copy of a string while checking for errors
#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
// Get a string
char *s = get_string("s: "); //this is in the cs50.h
char *t = malloc((strlen(s) + 1) * sizeof(char));
// Copy string into memory
for (int i = 0, n = strlen(s); i <= n; i++)
t[i] = s[i];
return 0;
}
The above code is from cs50 2018 lecture #3 . t[i] = s[i] part confused me. As I know, when we say char *t , t will store the address of the first part of the memory that was allocated. So doesn't t[i] give us the address of the memory at t[i] location ? If it is like so, shouldn't we write
*t[i] = s[i] to change the value of t[i] ?
No, the [] array index operator dereferences the pointer and evaluates to the value itself, not its address. The expression s[i] is equivalent to the expression *(s + i). If you wanted the address of the element at index i, you would need to use the & operator, as in &s[i] (which is equivalent to s + i).
int array[] = { 10, 20, 30, 40 }; // create an array for illustration
int *ptr = array; // array type decays to a pointer
// these print the same thing: the address of the array element at index 2
printf("%p\n", ptr + 2); // pointer arithmetic
printf("%p\n", &ptr[2]); // array index operator followed by address-of operator
// these print the same thing: the element at index 2 (= 30)
printf("%d\n", *(ptr + 2)); // pointer arithmetic followed by dereference operator
printf("%d\n", ptr[2]); // array index operator
t[i] actually gives you the ith element of the array. It works the same as s[i], which has the same type.
The syntax t[i] is exactly the same as *(t + i). In other words, pointer arithmetic is performed to get a pointer to the desired element, then the result is dereferenced to get the actual element.
char *s = ...;
char *t = ...;
...
t[i] = s[i];
t[i] is an lvalue, an expression that refers to an object. Oversimplifying a bit [*], if it appears on the left side of an assignment (as it does here), it refers to a particular char object, and the assignment updates the value of that object. s[i] is similar, but it appears on the right side of the assignment, so it yields the value of the object.
It's essentially the same thing as:
int x;
int y;
y = x;
x and y are both names of objects, and they're both lvalues. The y on the left hand side refers to the object. The x on the right hand side yields the value stored in the object.
[*] The oversimplification is that there are contexts other than the left hand side of an assignment in which an lvalue refers to an object rather than yielding its value.
There's a bit more going on here in the way the [] operator is defined (see the comp.lang.c FAQ) section 6 for the relationship between arrays and pointers), but in this case all you really need to know is that s[i] and t[i] are the names of objects.
The gory details are in the C standard, N1570 draft, section 6.3.2.1.
Related
Normally, when trying to reference the value of a pointer, one would use &p for the pointer p, so if I have a for loop that iterates through p, a pointer that points to an array, and I want to compare the value of p to that of p+1 I've ran into a bit of an issue. When I type
if(&p < &(p+1){
foo();
}
and in response, I get this error:
error: lvalue required as unary '&' operand
It's worth noting I'm using C89 and the assignment I'm doing doesn't allow me to access the array values directly with arr[value], it's unfortunately required for what I'm writing this for. How do I go about accessing the value of p+1?
The & operator returns the address of its operand. You want the value, which is the * operator for dereferencing.
if (*p < *(p+1)) {
foo();
}
Of course, you have to ensure that you don't do this when p points to the last element of the array, since p+1 points outside the array.
You must use the *p instead &p if you are going to reference the value of pointer 'p'. The '&' operand is the address of 'p', not a value.
So, you must do like this:
if (*p < *(p + 1)){
foo();
}
I suggest one sample below
void foo()
{
printf("foo\n");
}
int main()
{
int arr[5] = {1, 2, 3, 4, 5} ;
int * p = arr;
for (int i = 0; i < 4; i++)
{
if (*p < *(p + 1))
{
foo();
}
p++;
}
return 0;
}
Can anyone explain the logic how to add a and b?
#include <stdio.h>
int main()
{
int a=30000, b=20, sum;
char *p;
p = (char *) a;
sum = (int)&p[b]; //adding a and b!
printf("%d",sum);
return 0;
}
The + is hidden here:
&p[b]
this expression is equivalent to
(p + b)
So we actually have:
(int) &p[b] == (int) ((char *) a)[b]) == (int) ((char *) a + b) == a + b
Note that this technically invokes undefined behavior as (char *) a has to point to an object and pointer arithmetic outside an object or one past the object invokes undefined behavior.
C standard says that E1[E2] is equivalent to *((E1) + (E2)). Therefore:
&p[b] = &*((p) + (b)) = ((p) + (b)) = ((a) + (b)) = a + b
p[b] is the b-th element of the array p. It's like writing *(p + b).
Now, when adding & it'll be like writing: p + b * sizeof(char) which is p + b.
Now, you'll have (int)((char *) a + b) which is.. a + b.
But.. when you still have + in your keyboard, use it.
As #gerijeshchauhan clarified in the comments, * and & are inverse operations, they cancel each other. So &*(p + b) is p + b.
p is made a pointer to char
a is converted to a pointer to char, thus making p point to memory with address a
Then the subscript operator is used to get to an object at an offset of b beyond the address pointed to by p. b is 20 and p+20=30020 . Then the address-of operator is used on the resulting object to convert the address back to int, and you've got the effect of a+b
The below comments might be easier to follow:
#include <stdio.h>
int main()
{
int a=30000, b=20, sum;
char *p; //1. p is a pointer to char
p = (char *) a; //2. a is converted to a pointer to char and p points to memory with address a (30000)
sum = (int)&p[b]; //3. p[b] is the b-th (20-th) element from address of p. So the address of the result of that is equivalent to a+b
printf("%d",sum);
return 0;
}
Reference: here
char *p;
p is a pointer (to element with size 1 byte)
p=(char *)a;
now p points to memory with address a
sum= (int)&p[b];
p pointer can be use as array p[] (start address (in memory) of this array is a)
p[b] means to get b-th element - this element address is a+b
[ (start address)a + b (b-th element * size of element (1 byte)) ]
&p[b] means to get address of element at p[b] but its address is a+b
if you use pointer to int (mostly 4 bytes)
int* p
p = (int*)a;
your sum will be a+(4*b)
int a=30000, b=20, sum;
char *p; //1. p is a pointer to char
p = (char *) a;
a is of type int, and has the value 30000. The above assignment converts the value 30000 from int to char* and stores the result in p.
The semantics of converting integers to pointers are (partially) defined by the C standard. Quoting the N1570 draft, section 6.3.2.3 paragraph 5:
An integer may be converted to any pointer type. Except as previously
specified, the result is implementation-defined, might not be
correctly aligned, might not point to an entity of the referenced
type, and might be a trap representation.
with a (non-normative) footnote:
The mapping functions for converting a pointer to an integer or an
integer to a pointer are intended to be consistent with the addressing
structure of the execution environment.
The standard makes no guarantees about the relative sizes of types int and char*; either could be bigger than the other, and the conversion could lose information. The result of this particular conversions is very unlikely to be a valid pointer value. If it's a trap representation, then the behavior of the assignment is undefined.
On a typical system you're likely to be using, char* is at least as big as int, and integer-to-pointer conversions probably just reinterpret the bits making up the integer's representation as the representation of a pointer value.
sum = (int)&p[b];
p[b] is by definition equivalent to *(p+b), where the + denotes pointer arithmetic. Since the pointer points to char, and a char is by definition 1 byte, the addition advances the pointed-to address by b bytes in memory (in this case 20).
But p is probably not a valid pointer, so any attempt to perform arithmetic on it, or even to access its value, has undefined behavior.
In practice, most C compilers generate code that doesn't perform extra checks. The emphasis is on fast execution of correct code, not on detection of incorrect code. So if the previous assignment to p set it to an address corresponding to the number 30000, then adding b, or 20, to that address will probably yield an address corresponding to the number 30020.
That address is the result of (p+b); now the [] operator implicitly applies the * operator to that address, giving you the object that that address points to -- conceptually, this is a char object stored at an address corresponding to the integer 30020.
We immediately apply the & operator to that object. There's a special-case rule that says applying & to the result of a [] operator is equivalent to just doing the pointer addition; see 6.5.3.2p2 in the above referenced standard draft.
So this:
&p[b]
is equivalent to:
p + b
which, as I said above, yields an address (of type char*) corresponding to the integer value 30020 -- assuming, of course, that integer-to-pointer conversions behave in a certain way and that the undefined behavior of constructing and accessing an invalid pointer value don't do anything surprising.
Finally, we use a cast operator to convert this address to type int. Conversion of a pointer value to an integer is also implementation-defined, and possibly undefined. Quoting 6.3.2.3p6:
Any pointer type may be converted to an integer type. Except as
previously specified, the result is implementation-defined. If the
result cannot be represented in the integer type, the behavior is
undefined. The result need not be in the range of values of any
integer type.
It's not uncommon for a char* to be bigger than an int (for example, I'm typing this on a system with 32-bit int and 64-bit char*). But we're relatively safe from overflow in this case, because the char* value is the result of converting an in-range int value. there's no guarantee that converting a given value from int to char* and back to int will yield the original result, but it commonly works that way, at least for values that are in range.
So if a number of implementation-specific assumptions happen to be satisfied by the implementation on which the code happens to be running, then this code is likely to yield the same result as 30000 + 20.
Incidentally, I've worked on a system where this would have failed. The Cray T90 was a word-addressed machine, with hardware addresses pointing to 64-bit words; there was no hardware support for byte addressing. But char was 8 bits, so char* and void* pointers had to be constructed and manipulated in hardware. A char* pointer consisted of a 64-bit word pointer with a byte offset stored in the otherwise unused high-order 3 bits. Conversions between pointers and integers did not treat these high-order bits specially; they were simply copied. So ptr + 1 and (char*)(int)ptr + 1) could yield very different results.
But hey, you've managed to add two small integers without using the + operator, so there's that.
An alternative to the pointer arithmetic is to use bitops:
#include <stdio.h>
#include <string.h>
unsigned addtwo(unsigned one, unsigned two);
unsigned addtwo(unsigned one, unsigned two)
{
unsigned carry;
for( ;two; two = carry << 1) {
carry = one & two;
one ^= two;
}
return one;
}
int main(int argc, char **argv)
{
unsigned one, two, result;
if ( sscanf(argv[1], "%u", &one ) < 1) return 0;
if ( sscanf(argv[2], "%u", &two ) < 1) return 0;
result = addtwo(one, two);
fprintf(stdout, "One:=%u Two=%u Result=%u\n", one, two, result );
return 0;
}
On a completely different note, perhaps what was being looked for was an understanding of how binary addition is done in hardware, with XOR, AND, and bit shifting. In other words, an algorithm something like this:
int add(int a, int b)
{ int partial_sum = a ^ b;
int carries = a & b;
if (carries)
return add(partial_sum, carries << 1);
else
return partial_sum;
}
Or an iterative equivalent (although, gcc, at least, recognizes the leaf function and optimizes the recursion into an iterative version anyway; probably other compilers would as well)....
Probably needs a little more study for the negative cases, but this at least works for positive numbers.
/*
by sch.
001010101 = 85
001000111 = 71
---------
010011100 = 156
*/
#include <stdio.h>
#define SET_N_BIT(i,sum) ((1 << (i)) | (sum))
int sum(int a, int b)
{
int t = 0;
int i = 0;
int ia = 0, ib = 0;
int sum = 0;
int mask = 0;
for(i = 0; i < sizeof(int) * 8; i++)
{
mask = 1 << i;
ia = a & mask;
ib = b & mask;
if(ia & ib)
if(t)
{
sum = SET_N_BIT(i,sum);
t = 1;
/*i(1) t=1*/
}
else
{
t = 1;
/*i(0) t=1*/
}
else if (ia | ib)
if(t)
{
t = 1;
/*i(0) t=1*/
}
else
{
sum = SET_N_BIT(i,sum);
t = 0;
/*i(1) t=0*/
}
else
if(t)
{
sum = SET_N_BIT(i,sum);
t = 0;
/*i(1) t=0*/
}
else
{
t = 0;
/*i(0) t=0*/
}
}
return sum;
}
int main()
{
int a = 85;
int b = 71;
int i = 0;
while(1)
{
scanf("%d %d", &a, &b);
printf("%d: %d + %d = %d\n", ++i, a, b, sum(a, b));
}
return 0;
}
Below is a piece of code copied from a website.
The value set for the direction prints the respective character from "nsew". For example the output of this code is character w.
I am wondering how does it work.
#include<stdio.h>
void main (void){
int direction = 3;
char direction_name = direction["nsew"];
printf("%c",direction_name);
}
This is because the array subscript operator is commutative, i.e., this:
const char *p = "Hello";
char x = p[0];
Is equivalent to
const char *p = "Hello";
char x = 0[p];
Weird, huh? In your case you are indexing into the third position of the string literal (which is an array) "nsew".
some_ptr[n] is equivalent to *(some_ptr + n), and since addition is commutative, it is also equivalent to *(n + some_ptr). It then follows that n[some_ptr] is also an equivalent expression.
I wouldn't recommend using this "feature" however... seriously, don't do it.
Operator [] has the same semantics as pointer arithmetics. So a[i] is equivalent to *(a + i) which is equivalent to *(i + a) which is equivalent to i[a]:
So direction["nsew"] == "nsew"[direction] == "nsew"[3] == 'w'
So I have the following code snippet:
#include <stdio.h>
void pointer_shift(int *a, int n);
int main(void) {
int a[] = {100, 101, 102};
pointer_shift(a1, 3);
}
void pointer_shift(int *a, int n) {
int i;
for (i = 0; i != n - 1; i++) {
*(a + i) = *(a + i + 1);
}
}
I just want to clarify how the pointers work in this snippet. So pointer_shift takes in 'a', a pointer to an int, correct? a1 is passed in to this parameter, and since arrays decay to a pointer to their first element, it works.
First of all, hopefully what I said in the above paragraph is correct. Secondly, what does *(a + i) = *(a + i + 1); actually do? Say we're on the first iteration of the for loop, and i = 0. Then the left side, *a, accesses what, exactly? Does it represent a pointer? I thought * was the dereferencing operator, and accesses the object that a pointer points to... And so then it sets *a = *(a + 1). (a + 1) is the next element in the array, but what exactly does this assignment do, and why?
Thanks!
It is actually not pointer shift, but value shift, *(a+i) is of same effect as a[i], so what it does is a[i] = a[i+1]
*(a + i) = *(a + i + 1); is copying array elements within the array using a bit of pointer arithmetic.
*(a + i) is equivalent to a[i], so the statement is equivalent to a[i] = a[i + 1];. The loop is moving the array values "to the left" in the array: a[0] = a[1]; a[1] = a[2]; and so on.
Your understanding of the function call is correct.
I just want to clarify how the pointers work in this snippet. So pointer_shift takes in 'a', a pointer to an int, correct? a1 is passed in to this parameter, and since arrays decay to a pointer to their first element, it works.
Yes, when you pass an array to a function it degrades to a pointer. An array is not a pointer in an object sense, but it is a pointer in a value sense. When you pass it to a function its value is passed, i.e., a pointer to the first element.
array indexing is the same as pointer arithmetic, so the last two lines in this snippet are equivalent:
int arr[] = {1, 2, 3};
arr[0] = 10;
*arr = 10;
as are these:
arr[1] = 20;
*(arr + 1) = 20;
The expression a + i is pointer arithmetic, incrementing the memory address stored in a by i units of the pointer size of a. So if a pointer to an int takes four bytes on your system, and if the current memory address is, say, 0x1234 the value of a + 1 would be 0x1238.
What the asterisk does is dereference that address and access the actual value at that address. If you have 100 stored at a or a[0], and 101 stored at a + 1 or a[1], then *(a + i) = *(a + i + 1) replaces 100 with 101 at a[0], for i = 0.
Basically, you want to read this C tutorial on pointers and arrays.
Why the last printf in the main function doesn't print to the screen the value 10?
I know that in ANSI C, statically allocated matrix are arranged in memory in this way:
matrix: matrix[0][0], matrix[0][1],...,matrix[0][ColumnsDimension-1],matrix[1][0], etc
#include <stdio.h>
#include <stdlib.h>
#define dimRighe 20
#define dimColonne 30
int main()
{
int matrice[dimRighe][dimColonne];
int i,j;
for(i=0;i<dimRighe;i++)
for(j=0;j<dimColonne;j++)
matrice[i][j] = i+j;
matrice[0][3] = 10;
i = 0; j = 3;
printf("%d",*matrice[i*dimColonne+j]);
return 0;
}
Use *(matrice[i * dimColonne] + j) instead.
Why the last printf in the main function doesn't print to the screen the value 10?
Because matrice is an array of arrays ...
and matrice[whatever] is an array (which in most circunstances "decays" to a pointer to its first element)
and *matrice[whatever] is the contents of the first element of the array matrice[whatever].
In your code you have:
matrice[i*dimColonne+j]
Since i is 0 this evaluates to
matrice[j]
Since j is 3 this means
matrice[3]
When you print *matrice[3] that is equivalent to printing matrice[3][0] because matrice[3] is an array. And an array decays to a pointer to its first element.
But you don't want to do it this way at all. You should simply write matrice[i][j] and let the compiler do the work.
Change
printf("%d",*matrice[i*dimColonne+j]);
to simply be
printf("%d", matrice[i][j]);
if all you're worred about is printing out the right value. After all, that's how you assigned it.
If you're doing this as an exercise to understand how array subscripting works, then there are several things you need to remember.
First, except when it is the operand of the sizeof or unary & operators, or is a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T" will be replaced with ("decay to") an expression of type "pointer to T", and its value will be the address of the first element of the array. The expression matrice is an array expression of type "20-element array of 30-element array of int"; in most circumstances, it will be converted to an expression of type "pointer to 30-element array of int", or int (*)[30]. Similarly, the expression matrice[i] is an expression of type "30-element array of int", and in most cirumstances it will be converted to an expression of type "pointer to int", or int *.
Here's a handy table to remember all of this:
Declaration: T a[N];
Expression Type Decays to
---------- ---- ---------
a T [N] T *
&a T (*)[N]
*a T
a[i] T
Declaration: T a[M][N];
Expression Type Decays to
---------- ---- ---------
a T [M][N] T (*)[N]
&a T (*)[M][N]
*a T [N] T *
a[i] T [N] T *
&a[i] T (*)[N]
*a[i] T
a[i][j] T
Second, the subscripting operation a[i] is defined as *(a + i); that is, you compute an address based on i number of elements (NOT BYTES) from the base address of your array and dereference the result. For example, if a is an array of int, then *(a + i) will give you the value of the i'th integer after a. If an is an array of struct foo, then *(a + i) will give you the value of the i'th struct after a. Pointer arithemtic always takes the size of the base type into account, so you don't need to worry about the number of bytes in the offset.
The same logic applies to multidimensional arrays, you just apply the rule recursively for each dimension:
a[i][j] == *(a[i] + j) == *(*(a + i) + j)
a[i][j][k] == *(a[i][j]+ k) == *(*(a[i] + j) + k) == *(*(*(a + i) + j) + k)
Note that you should almost never have to do these dereferences manually; a compiler knows what an array access looks like and can optimize code accordingly. Under the right circumstances, writing out the dereferences manually can result in slower code than using the subscript operator.
You can index into a 2-d array as if it were a 1-d array like so:
a[i*rows + j] = val;
but I wouldn't (the types of the expressions don't match up cleanly). Note that you multiply i by the number of rows, not columns.
You could also print it like this:
char *matrixAsByteArray = (char *) matrice;
char *startIntAddr = matrixAsByteArray + i * dimColonne * sizeof(int) + j * sizeof(int);
int outInt = *startIntAddr | *(startIntAddr + 1) << 8 | *(startIntAddr + 2) << 16 | *(startIntAddr + 3) << 24;
printf("%d", outInt);
What this does is first, it converts your matrix to an array of bytes, then, it gets the starting address of the integer you need, and then it reconstructs the integer from the first four bytes read from that address.
This is a bit overkill, but a fun solution to the problem.