I am studying for my midterm. this was an example code
#include <stdio.h>
void doubleArray(int array[], int length)
{
for (int i = 0; i < length-2; i++) {
array[i] += array[i];
}
length += 5;
printf(“%d\n”, length); // Question 29
}
int main(int argc,char *argv[]) {
int integers[6] = { 3, 4, 5, 6, 7, 8};
int length = 6;
printf(“%d\n”, integers[4]); // Question 28
doubleArray(integers, length);
printf(“%d\n”, *(integers + 3)); // Question 30
printf(“%d\n”, *(integers + 4)); // Question 31
printf(“%d\n”, length); // Question 32
}
for questions 30 and 31
the answer is that it prints 12 (30) and 7 (31)
can someone explain to me why and what that "*(integers + 3)" means?
* is a dereference operator on a pointer.
This means that it will "get" the value that's stored at the pointer address of the item right after it ((integers + 3)).
It will interpret this value as the dereferenced type of the item after it (int since (integers + 3) is of type int*)
(integers + 3)
integers is a pointer to the address of the first element of the integers array.
That means that if integers contained [1, 2, 3, 4, 5] then it would point to where 1 is stored in memory.
integers + 3 takes the address of integers (i.e. where 1 is stored in memory) and adds the amount of address space required to store 3 ints (since the pointer is of type int*). Advancing it by one space would give you the address of 2 in memory, advancing it by two spaces would give you the address of 3 in memory, and advancing it by three spaces gives you the address of 4 in memory.
How this applies to your example
(integers + 3) gives you the address of the 4th item in the integers array since it's the first element's address plus the size of three elements.
Dereferencing that with the * operator, gives you the value of the 4th element, 12 (since the value of 6 was doubled by doubleArray)
The same applies to *(integers + 4) except that doubleArray didn't double the 5th element so it gives you 7.
How doubleArray works
for (int i = 0; i < length-2; i++) means start the variable i at 0 and advance it until it is length - 2.
This means it takes the value of everything from 0 to the value of length - 2 but executes the body of the loop for values from 0 to length - 3 since the < is exclusive (the conditional is evaluated BEFORE executing the body of the loop so when i == length - 2 the condition is false and the loop terminates without further execution.
So, for each element, excluding the last two, the element in array is added to itself.
Related
I don't understand why strlen() is giving wrong value (ie: 9) only for the first string. After that the values are coming correctly.
#include <stdio.h>
#include <string.h>
int main() {
int m, i, j;
i = 2;
j = 5;
char a[i][j];
for (i = 0; i <= 2; i++) {
scanf("%s", a[i]);
}
m = strlen(a[0]);
printf("%d\n", m); //here the problem is coming//
m = strlen(a[1]);
printf("%d\n", m);
m = strlen(a[2]);
printf("%d\n", m);
return 0;
}
INPUT:
heyman
jack
bro
OUTPUT:
9
4
3
Each row of a is only 5 bytes. When you read heyman into a[0], it overflows into a[1]. So you have:
a[0] = "heyma"
a[1] = "n\0"
Then when you read into a[1], you have
a[0] = "heyma"
a[1] = "jack\0"
Notice that there's no null terminator in a[0]. So when you call strlen(a[0]), it goes past the end of a[0] and continues searching in a[1] for the null byte. There are 5 bytes in a[0] and 4 bytes in a[1], so the length is 9. Technically, this is undefined behavior, but this is what happens in actual implementations because 2-dimensional arrays are contiguous.
In addition, when you read into a[2] you're completely outside the a array, resulting in undefined behavior.
Since your array has length [2][5] you can store a maximum of 2 words of length 4, every word also has the terminating character \0 in addition to its letters.
You having as input heyman means you are writing too many letters and don't have enough space to also store the \0. Either try with a shorter word or change your length from 5 to 7.
Also you are storing 3 words in your array of length 2, the length refers to the number of elements stored not to the number you can go up to. Length 2 will have available positions 0 and 1 so when you are passing as input the third word you are trying to write outside of the array bounds.
This question already has answers here:
How do I determine the size of my array in C?
(24 answers)
Closed 5 years ago.
I'm writing a function that is supposed to split a string on "-" and return and array containing the parts from the string, so if the string is:
2017-10-23
I want the array to have three elements populated like:
arr[0] = 2017, arr[1] = 10, arr[2] = 23
This is the function:
/*
* return a array of the parts of date_string
*/
int * to_date_array(char *date_string)
{
int i = 0;
int f = 0;
char *tokens = strtok(date_string, "-"); /* get initial token */
static int arr[3] = {0, 0, 0};
char *ptr;
int val;
/* init static arr */
for (f = 0; f < sizeof(arr); f++)
arr[f] = 0;
/* do the split */
while (tokens != NULL) {
val = strtol(tokens, &ptr, 10);
arr[i++] = val;
tokens = strtok(NULL, "-");
}
/*
* for some reason arr becomes 12 elements long?
* I expected it to have 3 elements
*/
puts("func: to_date_array");
puts("------------------------");
for (f = 0; f < sizeof(arr); f++)
printf("arr[%d]: %d\n", f, arr[f]);
return arr;
}
The function works but I'm really puzzled by the "arr" array. I expect it to be three elements long but when I iterate through it and print every element, it show 12 elements?
$ gcc -Wall main.c arguments.c -o timespan
$ ./timespan 2015-08-10 2017-10-18
func: to_date_array
------------------------
arr[0]: 2015
arr[1]: 8
arr[2]: 10
arr[3]: 0
arr[4]: 0
arr[5]: 0
arr[6]: 0
arr[7]: 0
arr[8]: 0
arr[9]: 0
arr[10]: 0
arr[11]: 0
The sizeof operand returns a size in bytes (where by definition a char takes one byte). On your (and mine) machine, sizeof(int) is 4, hence an array of 3 int takes 12 bytes. See nucleon's answer.
Your to_date_array is not reentrant. It would be nicer to return a dynamically allocated array (e.g. with calloc ....). Of course you need then to adopt the convention that its result has to be later free-d (e.g. by the caller).
You could consider also returning a pointer to some struct ending with a flexible array member.
You could also pass arr (and its length) to the to_date_array and have it been filled by that function.
sizeof computes the size of the array in bytes, thus you have to divide by the size of a single element to get the number of elements, thus use
sizeof(arr)/sizeof(*arr)
sizeof returns the number of bytes in the array, not the number of elements. On your system, an int is 4 bytes wide, so the array takes up 12 bytes.
You need to divide the size of the array by the size of a single element to get the number of elements:
sizeof arr / sizeof *arr
C does not do any bounds checking on array access - the array is only three elements wide, but you won't get any sort of OutOfBounds exception if you attempt to access elements outside of that range. The behavior is undefined - your code may crash, it may produce unexpected results, it may work as intended, but the results won't necessarily be repeatable or predictable.
sizeof int arr[3] is sizeof(int) * 3 equals to 4*3 = 12
I recently learnt nios II SOPC, and I encountered the process of writing into and reading from memory. The use of pointer int* and char* lets me have two different results. The code is as follow.
#include "system.h"
#include "stdio.h"
int main()
{
char* n = (char*) MEMORY_0_BASE; //the address for first block of memory
int i;
for(i=0;i<16;i++)
{
*(n+i)=i;
}
for(i=0;i<16;i++)
{
printf("Du lieu tai o nho thu %d la %d\n", i , *(n+i));
}
while(1);
}
The code for "int*" is as follow
#include "system.h"
#include "stdio.h"
int main()
{
char* n = (char*) MEMORY_0_BASE; //the address for first block of memory
int i;
for(i=0;i<16;i++)
{
*(n+i)=i;
}
for(i=0;i<16;i++)
{
printf("Du lieu tai o nho thu %d la %d\n", i , *(n+i));
}
while(1);
}
The result for using "int*" is 0,1,2,...,15 while the result for "char*" is 3,3,3,3,7,7,7,7,11,11,11,11,15,15,15,15. I cannot explain why this is the case.
The following is my code for the memory block
module memory
#(parameter DATA_WIDTH=32, parameter ADDR_WIDTH=4)
(
input iClk, iReset_n,
input iRead_n, iWrite_n,
input [ADDR_WIDTH-1:0] iAddress,
input [DATA_WIDTH-1:0] iData,
output [DATA_WIDTH-1:0] oData
);
reg [DATA_WIDTH-1:0] mem [2**ADDR_WIDTH-1:0];
reg [ADDR_WIDTH-1:0] addr_reg;
always#(posedge iClk)
begin
if(!iWrite_n)
mem[iAddress] = iData;
if(!iRead_n)
addr_reg = iAddress;
end
assign oData = mem[addr_reg];
endmodule
This is my speculation based on the observed behaviour.
Your memory device consists of 16 x 32-bit integers. My speculation is that the compiler which likes to address things in bytes is effectively masking out the lowest two bits of the address. The zeroth register has the address MEMORY_0_BASE + 0 * 4, the first register has the address MEMORY_0_BASE + 1 * 4, the second register has the address MEMORY_0_BASE + 2 * 4 etc.
If you store ints to the registers using an int pointer, each time you increment the int pointer, the C pointer arithmetic actually adds sizeof(int) = 4 to the address in the pointer, so the sequence of addresses to which ints are stored is as above.
If you store chars using a char pointer, each time you increment the char pointer, the C pointer arithmetic adds sizeof(char) = 1 to the address in the pointer. The code attempts to store the first four chars (0, 1, 2, 3) to MEMORY_0_BASE + 0, MEMORY_0_BASE + 1, MEMORY_0_BASE + 2, MEMORY_0_BASE + 3. If, as I believe, the bottom two bits of the pointer are being masked, all of those addresses store to MEMORY_0_BASE and, by the time you are done, the value in it is 3.
Similarly for the second four chars (4, 5, 6, 7). They get stored to MEMORY_0_BASE + 4, MEMORY_0_BASE + 5, MEMORY_0_BASE + 6, MEMORY_0_BASE + 7, which all map to MEMORY_0_BASE + 4 after masking, leaving it containing the number 7 and so on.
That's how you get the sequence 3,3,3,3,7,7,7,7,11,11,11,11,15,15,15,15.
I came along a competitive question that asks the output of the following:
#include <stdio.h>
int main()
{
int a[] = {0,1,2,3,4};
int i, *ptr;
for(ptr = a+4, i=0; i <=4; i++)
printf("%d", ptr[-i]);
return 0;
}
I did read this topic: Are negative array indexes allowed in C? However it was unclear to me how the -ve symbol generates the array in the reverse order, ie. 4, 3, 2, 1, 0.
First, recall that in C the expression ptr[index] means the same thing as *(ptr+index).
Now let's look at your expression again: ptr is set to a+4 before the loop; then you apply -i index to it. Therefore, the equivalent pointer arithmetic expression would be as follows:
printf("%d", *(a+4-i));
This expression iterates the array backwards, producing the results that you see.
The reason it works is because the [] operator does pointer addition.
When you reference
a[x]
Whats actually happening is its taking the memory address of a and adding the sizeof(int)*x
So if you set ptr to a+4, you are going to a+sizeof(int)*4
then, when you put in a negative value, you move backwards through the memory address.
ptr[-i] decays into *(ptr + (-i)). At the first iteration, when i = 0, ptr[-i] accesses last element of a array, because initially ptr was set to be equal a + 4, which means - take address of beginning of a and add 4 * sizeof(int) (because ptr was of size int). On every next iteration, when i is incremented, previous element of array is accessed.
In is for statement
for(ptr = a+4, i=0; i <=4; i++)
pointer ptr is set to a+4 It could be done also the following way
ptr = &a[4];
If you tray to output the value pointed to by the pointer as for example
printf( "%d\n", *ptr );
you will get 4. That is the pointer points to the last element of the array.
Inside the loop there is used expression ptr[-i] . for i equal to 0 it is equivalent to ptr[0] or simply to *ptr that is the last element of the array will be outputed.
For i equal to 1 expression ptr[-i] is equivalent to a[4 - 1] or simply a[3]. When iequal to 2 when expression ptr[-i] is equivalent to a[4 - i] that is a[4 - 2] that in turn is a[2] and so on.
SO you will get
4321
a+4 gives a pointer to the fifth element of a. So ptr refers to that location.
Then the loop counts i from 0 up to (and including) 4.
The dereference ptr[-i] is equivalent to *(ptr - i) (by definition). So, since i is 0 and ptr is a+4, it's equivalent to a+4-0, then a+4-1, then a+4-2, and so on until a+4-4, which is (obviously enough) equal to a.
As I mentioned in my comment in C/C++
a[b] == *(a+b) == b[a]
For your case all of these is fine
printf("%d", *(a + 4 - i));
printf("%d", a[4 - i]);
printf("%d", 4[a - i]);
...
I am trying to understand how the pointers are moving.
Following is the program and I am aware that
if
int cs={1,2,3};
then cs points to cs[0]
what I am not clear is what is *cs pointing to.
#include<stdio.h>
int main()
{
int array[] = { 1, 2, 3, 4, 5 };
int *arrptr1 = array;
int *arrptr = array;
int i;
for (i = 0; i < sizeof(array) / sizeof(int); i++) {
printf("%d, %d, %d\n", array[i], *arrptr1++, *arrptr + i);
}
}
the output of above program is
1, 1, 1
2, 2, 2
3, 3, 3
4, 4, 4
5, 5, 5
then my understanding *arrptr should increase the value stored at
*arrptr
should get incremented by 1.
Where as what I observe is the pointer is moving to next location.So just want to know what is wrong in my understanding?
UPDATE
As per the replies below I understand that
print("%d", *arrptr1++);
in such a statement evaluation of operators is from right to left.
Hence in *arrptr1++ the ++ will get evaluated first and then arrptr and then *
So to confirm the same I wrote another program
#include<stdio.h>
int main()
{
int array[] = { 10, 20, 30, 40, 50 };
int *q1 = array;
printf("q1 = %p\n",q1);
printf("*q1++ = %d\n",*q1++);
printf("q1 = %p\n",q1);
printf("*q1++ = %d\n",*q1);
}
The output of above program is different than the expected operator precedence by above logic.
The output I got is
q1 = 0x7ffffcff02e0
*q1++ = 10
q1 = 0x7ffffcff02e4
*q1++ = 20
So I was expecting in the 2nd line of output instead of *q1++ = 10 following *q1++ = 20
so did the operator precedence not happened right to left?
*arrptr1++ is parsed as *(arrptr1++), not (*arrptr1)++.
Whenever you use dereference operator * and pre-increment(pre-decrement) or post-increment(post-decrement) operator on a variable simultaneously ,the order of operation is from right to left (if parenthesis are not used).
What you want to do is
(*arrptr)++
because of higher precedence of (), it will force the compiler to first access the element pointed to by arrptr and then increment its value.
When you do this *arrptr++ , as I've said it first operates rightmost operator (i.e. ++)
and then the dereference operator.
If you will write
EDITED (only the comment): *++arrptr // increment the pointer then access
it will first advance the pointer and then access the value
stored in the address now pointed to by arrptr.
One more thing,The comma used for separation of function argument is not the comma operator so the order of evaluation of the arguments is undefined. (already been told)
What happens is that *arrptr1++ is interpreted as *(arrptr1++), which means that the pointer to the array is increased by one each time in the loop, and hence it will point to the same element as array[i]. *arrptr + i on the other hand is interpreted as "the value of the array element pointed to by arrptr plus the integer i". In this loop it means it will display the same thing as array[i], but it is not pointing at the same element (arrptr is always pointing to the first element in your array). If you change the values in the array to something more random, it should be obvious when you run the program again.
cs = &cs[0] ( cs is equal to the address of cs sub 0) ; *cs = cs[0] (cs pointer is equal to cs sub 0) ; You should remember that *'s hide the [].
// here is a print function with a pointer
int foo[5] = { 2, 9, 1, 3, 6};
int *walker, count;
walker = foo;
for (count = 0; count < 5; walker++, count++)
printf("Array[%d]: %d\n", count, *walker);
Recap: walker is equal to &foo[0], so when you increment walker (eg. walker++) you're moving the pointer to the next address which is foo[1]. And when we are printing the value we can't say ..., walker); since walker( &foo[whatever] ) is pointing to an address, we need to dereference the pointer to get the value. Again, the most important thing to remember
array = &array[0] AND *array = array[0]