I have been asked to sum up an int array and return the sum not using index.
(function needs to get the array and the size)
I know I should've set a pointer to the array and compare the pointer to the array address and use pointer++ to run over the array.
Tho, I wrote down the following code :
int sumArray(int nNumArray[], int nSize)
{
int nSum = 0;
while(*nNumArray <= &nNumArray[nSize-1])
{
nSum += *nNumArray;
nNumArray++;
}
return nSum;
}
which works perfectly,
thing is *nNumArray is referring to values and &nNumArray[nSize-1] is referring to an address.
I'm trying to understand how come this way works.
Will appreciate some insights. Thanks.
The while loop condition is incorrect:
while(*nNumArray <= &nNumArray[nSize-1])
because you are comparing an integer (*nNumArray) with a pointer (&nNumArray[nSize-1]). Compiler must be giving warning message on this statement.
Instead, you can do:
int sumArray(int nNumArray[], int nSize)
{
int nSum = 0;
while(nSize--)
{
nSum += *nNumArray;
nNumArray++;
}
return nSum;
}
"which works perfectly" : this is impossible
(*nNumArray <= &nNumArray[nSize-1]) : you compare an int into the vector (and later outside it) and an address of an int into the vector ( and in fact after its end). A priori your compiler signal the error
Furthermore &nNumArray[nSize-1] will not be the end of the vector after the first loop because you modify nNumArray
If you want to use a pointer you can use an other variable to store it to not modify nNumArray, and to change test like (ptr <= &nNumArray[nSize-1]) :
#include <stdio.h>
int sumArray(int nNumArray[], int nSize)
{
int nSum = 0;
int * ptr = nNumArray;
while(ptr <= &nNumArray[nSize-1])
{
nSum += *ptr++;
}
return nSum;
}
int main()
{
int a[3] = {1,2,3};
printf("%d\n", sumArray(a, 3));
return 0;
}
First error here :
(*nNumArray <= &nNumArray[nSize-1])
The name of the array variable itself is considered as a pointer in C, thus *nNumArray represents the reference of an pointer.
It should be nNumArray to make it compare the address.
Second error :
It won't work perfectly if only the first error is fixed.
The index operation works like this :
&nNumArray[nSize-1] works the same as nNumArray + nSize - 1
Thus the while loop might looks like this :
while(nNumArray <= nNumArray + nSize - 1){
nSum += *nNumArray;
nNumArray++;
}
(This might makes it more simple to see where is wrong)
The while loop will run forever until *nNumArray accessed an int which is out of the array that causes a segmentation fault.
You might want to do it by using another pointer to compare with nNumArray + nSize - 1, and the whole sumArray function should look like this:
int sumArray(int nNumArray[], int nSize)
{
int nSum = 0;
int *ptr = nNumArray;
while(ptr <= nNumArray + nSize - 1)
{
nSum += *ptr;
ptr++;
}
return nSum;
}
And now it should work perfectly :)
Related
I am new to the language and was trying a simple code. I wanted to try to create a loop based on pointers. but it seems like you can not promote variate location like in assembler. or i just did it wrong? and if i really can't can i force a new variadate to be born in specific location? that was my code
#include <stdio.h>
int main(void) {
int firstnumber = 1;
int *beginning = &firstnumber;
printf("%i %i \n",firstnumber,beginning);
Test1(firstnumber,beginning);
return 0;
}
Test1 (int num, int begin)
{
int reserve = num;
if(num != 100)
{
&num +=2;
num = (reserve+1);
return Test1(num, begin);
}
else
{
int assist = begin;
while(*assist != 100)
{
printf("/n \n %i %i \n /n",num,assist);
&assist += 2;
}
}
}
I know it might look ridiculous but i'm really curious
You're thinking about this backwards. Pointers are the variables you can move around, so use them for anything you want to move around.
firstnumber is an integer variable - the compiler decides where it is stored and you can't tell the compiler to rebind the name firstnumber to a different location. You can, however, move a pointer around as much as you like. So,
void Test1(int num) {
&num +=2;
num = 42;
}
is nonsense, but
void Test2(int *num) {
num += 2;
*num = 42;
}
is fine - so long as num+2 is still a valid allocated object. For example, you could call it like
int i[5];
Test2(i); /* sets i[2] = 42 */
(if you pass in an array of fewer than 3 integers you get a runtime bug rather than a compile error, as Test2 damages your stack frame or other memory it shouldn't be touching).
No, you cannot promote/change variable location.
So this:
int num;
&num +=2;
does not make sense, and will result in an error:
error: lvalue required as left operand of assignment
&num +=2;
^~
Same for:
int assist;
&assist += 2;
Your code will compile only if you modify these statements (but now the logic is changed, you should work on that), but now it will result in an infinite loop, since your function never returns in the else case:
#include <stdio.h>
void Test1 (int num, int* begin);
int main(void) {
int firstnumber = 1;
int *beginning = &firstnumber;
printf("%i %i \n",firstnumber, *beginning);
Test1(firstnumber, beginning);
return 0;
}
void Test1 (int num, int* begin)
{
int reserve = num;
if(num != 100)
{
num +=2;
num = reserve + 1;
return Test1(num, begin);
}
else
{
int assist = *begin;
while(assist != 100)
{
printf("/n \n %i %i \n /n",num,assist);
assist += 2;
}
}
}
Good luck!
OK i checked the code deeper and got several conclusions:
function variable can not inherit his ancestor adress. therefore using a function for the task is useless unless i use some static variable
I had another conclusion but i don't remember what it was. sorry and thank you for your time
I have coded a generic insertion sort in C, and it works really fine.
But, On my function of insertion sort, it gets a void** arr,
and on its signature it gets a void* arr, otherwise, it doesn't work.
Why is it so?
Do we have any other ways to code the insertion sort to be generic?
The Full code is here:
#include <stdio.h>
#include <malloc.h>
#define SIZE 10
int cmp(void* elm1, void* elm2);
void insertionSort(void* arr, int size);
int main()
{
int arr[] = {5, 8, 2, 3, 15, 7, 4, 9, 20, 13};
int arr2[] = {1};
int i;
for (i = 0; i < SIZE; i++)
printf("%d ", arr[i]);
printf("\n");
insertionSort(&arr, SIZE);
for (i = 0; i < SIZE; i++)
printf("%d ", arr[i]);
return 0;
}
void insertionSort(void** arr, int size)
{
int i = 1;
int j;
void* temp;
while (i < size)
{
if (cmp(arr[i], arr[i-1]) == -1)
{
temp = arr[i];
j = i - 1;
while (j >= 0 && cmp(arr[j], temp) == 1)
{
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = temp;
}
i++;
}
}
int cmp(void* elm1, void* elm2)
{
if ((int)elm1 == (int)elm2)
return 0;
else if ((int)elm1 > (int)elm2)
return 1;
else
return -1;
}
The code as it is, is undefined, because of multiple problems. It just happens to work, because on your system the size of the pointer is the same as the size of the type int.
You code will not compile without warnings (if you enable them). The function insertionSort and it's prototype must have the same type.
You should change the type in the function definition to
void insertionSort(void* arr, int size)
And then cast the pointer arr, to an appropriate type. Since this is a generic sort, like qsort(), the only realistic option is a cast to char*. This means you will also have to pass the size of the type into the function, so the pointer can be incremented correctly. This will require you to change the function drastically.
So, the function prototype should really be the same as qsort:
void Sort(void* arr, size_t size , size_t object_size , int(*)( const void* , const void* ))
The problem is that integers are not pointers, so your test array is of type *int or int[]. But in your function, you don't know that and you try to make your code work with pointers. So you expect * void[]. If you change your temp variable to int, you don't need the ** in the signature. The same way, if you want to keep the "generic" (as you call), you need an array of *int.
Basically, in C you cannot write a function working out of the box for both primary types and pointers. You need some tricks. Have a look at this stackoverflow, maybe it will help.
I'm new to C and still learning about pointers. I was just testing my understanding of pointers by trying to simulate appending to an array when I got an Access Violation Read Loaction error when using printf. This is the code:
#include <stdio.h>
#include <stdlib.h>
int arraySize(int *arrayToSize);
void changeAll(int ***a1PtrPtrPtr, int nToAdd){
int *bPtr = (int *)malloc((arraySize(**a1PtrPtrPtr) + 1) * sizeof(int));
int i = 0;
while (*(**a1PtrPtrPtr + i) != -1){
bPtr[i] = *(**a1PtrPtrPtr + i);
i++;
}
bPtr[i] = nToAdd; i++;
bPtr[i] = -1;
*a1PtrPtrPtr = &bPtr;
}
int main(void){
int a[4] = { 1, 2, 3, -1 };
int *aPtr = a;
int **aPtrPtr = &aPtr;
int ***aPtrPtrPtr = &aPtrPtr;
int n = 4;
changeAll(aPtrPtrPtr, n);
int counter = 0;
while (counter < 5){
int temp = *(*aPtrPtr + counter);
printf("%d is %d", counter, temp );
counter++;
}
return 0;
}
int arraySize(int *arrayToSize){
int sizeTemp = 0;
int i = 0;
while (arrayToSize[i] != -1){
sizeTemp++;
i++;
}
sizeTemp++;
return sizeTemp;
}
I get the error the second time I print in the while loop in main() when counter = 1. What I don't understand is that if I comment out that printf statement and look at the value of temp value in my IDE (MVSE 2013) it is exactly as I wanted and expected i.e. temp will be 1 then 2,3,4,-1.
What is going on please and thanks in advance for any help.
Firstly, in case you're wondering how this appeared to sometimes work, you really should read this stellar answer to another somewhat related question.
In short, you're saving an address to an automatic variable from inside a function, then treating said-address like it is still valid after the function returns. That the automatic variable is a pointer referring to dynamic data is irrelevant. The variable itself is no longer valid once the function expires, and thus dereferencing its use-to-be-address invokes undefined behavior:
void changeAll(int ***a1PtrPtrPtr, int nToAdd)
{
// NOTE: local variable here
int *bPtr = (int *)malloc((arraySize(**a1PtrPtrPtr) + 1) * sizeof(int));
int i = 0;
while (*(**a1PtrPtrPtr + i) != -1){
bPtr[i] = *(**a1PtrPtrPtr + i);
i++;
}
bPtr[i] = nToAdd; i++;
bPtr[i] = -1;
// NOTE: saving address of local variable here
*a1PtrPtrPtr = &bPtr;
}
With how this is setup, the quickest fix is simply this:
**a1PtrPtrPtr = bPtr;
instead of what you have. This will save the dynamic allocation result to the correct location (which is ultimately the address held in aPtr back in main()). It looks hideous (and frankly, it is), but it will work.
Best of luck.
I'm a java student who's currently learning about pointers and C.
I tried to make a simple palindrome tester in C using a single array and pointer arithmetic.
I got it to work without a loop (example for an array of size 10 :*(test) == *(test+9) was true.
Having trouble with my loop. School me!
#include<stdio.h>
//function declaration
//int palindrome(int *test);
int main()
{
int output;
int numArray[10] = {0,2,3,4,1,1,4,3,2,0};
int *ptr;
ptr = &numArray[0];
output = palindrome(ptr);
printf("%d", output);
}
//function determine if string is a palindrome
int palindrome(int *test) {
int i;
for (i = 0; i <= (sizeof(test) / 2); i++) {
if (*(test + i) == *(test + (sizeof(test) - i)))
return 1;
else
return 0;
}
}
The Name of the array will itself acts as a pointer to an first element of the array, if you loose the pointer then there is no means for you to access the element of the array and hence you can send just the name of the array as a parameter to the function.
In the palindrome function:
you have used sizeof(test)/2. what happens is the address gets divided which is meaningless and hence you should not use that to calculate the mid element.
sizeof the pointer will be the same irrespective of the type of address that gets stored.
Why do you copy your pointer in another variable?
int *ptr;
ptr = &numArray[0];
Just send it to you function:
palindrome(numArray);
And sizeof(test) give you the memory size of a pointer, it's not what you want. You have to give the size in parameter of your function.
int palindrome(int *test, int size){
...
}
Finally your code must look like this:
#include<stdio.h>
int palindrome(int *test, int size);
int main()
{
int output;
int numArray[10] = {0,2,3,4,1,1,4,3,2,0};
output = palindrome(numArray, 10);
printf("%d", output);
}
//function determine if string is a palindrome
int palindrome(int *test, int size) {
int i;
for (i = 0; i < size / 2; i++) {
if (*(test + i) != *(test + (size - 1) - i))
return 0;
}
return 1;
}
I have written a program for insertion shot like following:
int _tmain(int argc, _TCHAR* argv[])
{
int arr[10] = {1,2,3,10,5,9,6,8,7,4};
int value;
cin >> value ;
int *ptr;
ptr = insertionshot(arr); //here Im passing whole array
BinarySearch(arr,value);
return 0;
}
int * insertionshot(int arr[])
{
//Changed after a hint (now, its fine)
int ar[10];
for(int i =0;i < 10; i++)
{
ar[i] = arr[i];
}
//Changed after a hint
int arrlength = sizeof(ar)/sizeof(ar[0]); //here array length is 1, it should be 10
for(int a = 1; a <= arrlength -1 ;a++)
{
int b = a;
while(b > 0 && ar[b] < ar[b-1])
{
int temp;
temp = ar[b-1];
ar[b-1] = ar[b];
ar[b] = temp;
b--;
}
}
return ar;
}
The problem is after passing the whole array to the function, my function definition only shows 1 element in array and also "arraylength" is giving 1.
int arr[] in a function formal parameter list is a syntax quirk, it is actually processed as int *arr. So the sizeof trick doesn't behave as you expect.
In C it is not possible to pass arrays by value; and furthermore, at runtime an array does not remember its length.
You could include the length information by passing a pointer to the whole array at compile time:
int * insertionshot(int (*arr)[10])
Of course, with this approach you can only ever pass an array of length 10. So if you intend to be able to pass arrays of differing length, you have to pass the length as another parameter.