swapping address values of pointers - pointers

Below is code and I want to ask, why I am not getting swapped number as a result, because instead of swapping numbers I tried to swap their addresses.
int *swap(int *ptr1,int *ptr2){
int *temp;
temp = ptr1;
ptr1= ptr2;
ptr2=temp;
return ptr1,ptr2;
}
int main(){
int num1=2,num2=4,*ptr1=&num1,*ptr2=&num2;
swap(ptr1,ptr2);
printf("\nafter swaping the first number is : %d\t and the second number is : %d\n",*ptr1,*ptr2);
}

I can see two problems in your code.
First, within the swap function, ptr1 and ptr2 are local copies of the pointers in main with the same name. Changing them in swap only changes those copies, not the originals.
Second, the return statement doesn't do anything useful. The function swap is declared as returning a single int *. The return statement actually only returns ptr2 - for why that is, look up the "comma operator" in C. But you ignore the return value in main anyway, so it makes no odds.

Related

Can argv** be returned as a function return value

In C we should return pointer variable if define as 1- static stack 2- Heap-allocated 3-const address.
The question is:
Can argv** variable in main function be returned as a function return value without undefined behaviour?
I can't imagine a situation which requires to return argv** from a function, but you get it from main (int argc, char* argv[]) so yes. You can pass it as a parameter to a function and return it to another function. They're like const for you.
You can't return pointer to the data allocated temporarily for the function's own needs. int* F{ int A; return &A; } will not work. But you can set int* A=(int*)malloc(sizeof(int)); and return A;: it'll be your tiny wrapper around the malloc function. You can even receive int* A as a parameter and return A+1; the rule you mentioned in the beginning actually means "there are some restrictions of allocation methods if you're planning to use the pointer after the function exits". You can break the rule without returning the value (for example, you can store the poiner in a global variable and it'll become invalid when the function exits, like void F{ int A; GlobPtr=&A; } which will cause the same problems).
But your function does not allocate argv, it's allocated before your code starts. So you can even shift it by one value as you extract parameters one-by-one, the returned pointer *nextargv[] will also point to valid memory area.

Need to understand how char * strcpy (char *cad1, const char *cad2) works in C

Can't get how a method with this head: char * strcpy (char *cad1, const char *cad2), works in C in this sample:
'char * strcpy (char *cad1, const char *cad2){
char *aux = cad1;
for( ; *cad1++ = *cad2++; );
return cad1;
}'
Starting from the method signature or prototype, that tells a lot about the how it works: we have two parameters together with their respective types and a return type. All parameters in this case are pointers to char, more known as char pointers. Those char pointers are what is used in "C" as strings of characters. One parameter is a const, because that value must not be changed in the function, it MUST keep, the original value.
Strings in "C" have some peculiarities, once the pointer is created to a string it always points to the first characters in the string or index 0, the same as char *v = var[0], and can be incremented passing to the next char in the string such as v++. Other peculiarity in "C" is that all strings represented by char arrays end with a 0 character (ASCII null = 0).
The strcpy version account on that concepts and makes a for loop to copy each element in the char *cad2 to *cad1, that variables MUST be allocated statically or dynamically (malloc) before calling the function, and the return of the function in the code above is a pointer to the original variable (in that case *cad1, normally they return the copied one). In your function it was changed, I mean it is returning the original instead of the copied what looks wrong since you catch in the aux the pointer to the first element of the copied variable and you did not use it.
One good point to observe is the for loop:
for( ; *cad1++ = *cad2++; );
How it works is tricky, the first interesting point is that the for loop has tree parameters, and in "C" all are optional. The first is to initialize, the second is a boolean condition to continuing iterating, and the last one is to increment or decrement.
Next, tricky is is *cad1++ = *cad2++ a boolean expression? The answer is yes, it is. Since in "C" the value 0 (zero) is false, and anything else is true. Remember that I have said strings in "C" finishes always with a 0 (zero), so when evaluating and assigning to the copy the value of a pointer (using *cad1 will return the value pointed by a pointer variable, the star in the begin makes that magic) and reaches the end of the string that will return false and finish the iteration loop.
One point is interesting here, first the evaluation has less priority than the assignment in this case, what makes first the value being copied to the copy variable, then evaluating the boolean expression.
"C" is like this you writes a small code that have large meaning behind it. I hope you have understood the explanation. For further information have a look in "C" pointers at : https://www.tutorialspoint.com/cprogramming/c_pointers.htm.
char * strcpy (char *cad1, const char *cad2){
for( ; *cad1++ = *cad2++;);
return cad1;
}
the way this works, at the calling side, it can be used in two ways, but always requires a buffer to write to so the use is simmilar.
char arr[255];
memset(arr,0,sizeof(char) * 255); // clear the garbage initialized array;
strcpy(arr, "this is the text to copy that is 254 characters long or shorter.");
puts(arr);
or
char arr[255];
memset(arr,0,sizeof(char) * 255);
puts(strcpy(arr,"hello C!"));
sense the function returns the pointer to the buffer this works as well.

Understanding the method for OpenCL reduction on float

Following this link, I try to understand the operating of kernel code (there are 2 versions of this kernel code, one with volatile local float *source and the other with volatile global float *source, i.e local and global versions). Below I take local version :
float sum=0;
void atomic_add_local(volatile local float *source, const float operand) {
union {
unsigned int intVal;
float floatVal;
} newVal;
union {
unsigned int intVal;
float floatVal;
} prevVal;
do {
prevVal.floatVal = *source;
newVal.floatVal = prevVal.floatVal + operand;
} while (atomic_cmpxchg((volatile local unsigned int *)source, prevVal.intVal, newVal.intVal) != prevVal.intVal);
}
If I understand well, each work-item shares the access to source variable thanks to the qualifier "volatile", doesn't it?
Afterwards, if I take a work-item, the code will add operand value to newVal.floatVal variable. Then, after this operation, I call atomic_cmpxchg function which check if previous assignment (preVal.floatVal = *source; and newVal.floatVal = prevVal.floatVal + operand; ) has been done, i.e by comparing the value stored at address source with the preVal.intVal.
During this atomic operation (which is not uninterruptible by definition), as value stored at source is different from prevVal.intVal, the new value stored at source is newVal.intVal, which is actually a float (because it is coded on 4 bytes like integer).
Can we say that each work-item has a mutex access (I mean a locked access) to value located at source address.
But for each work-item thread, is there only one iteration into the while loop?
I think there will be one iteration because the comparison "*source== prevVal.int ? newVal.intVal : newVal.intVal" will always assign newVal.intVal value to value stored at source address, won't it?
I have not understood all the subtleties of this trick for this kernel code.
Update
Sorry, I almost understand all the subtleties, especially in the while loop :
First case : for a given single thread, before the call of atomic_cmpxchg, if prevVal.floatVal is still equal to *source, then atomic_cmpxchg will change the value contained in source pointer and return the value contained in old pointer, which is equal to prevVal.intVal, so we break from the while loop.
Second case : If between the prevVal.floatVal = *source; instruction and the call of atomic_cmpxchg, the value *source has changed (by another thread ??) then atomic_cmpxchg returns old value which is no more equal to prevVal.floatVal, so the condition into while loop is true and we stay in this loop until previous condition isn't checked any more.
Is my interpretation correct?
If I understand well, each work-item shares the access to source variable thanks to the qualifier "volatile", doesn't it?
volatile is a keyword of the C language that prevents the compiler from optimizing accesses to a specific location in memory (in other words, force a load/store at each read/write of said memory location). It has no impact on the ownership of the underlying storage. Here, it is used to force the compiler to re-read source from memory at each loop iteration (otherwise the compiler would be allowed to move that load outside the loop, which breaks the algorithm).
do {
prevVal.floatVal = *source; // Force read, prevent hoisting outside loop.
newVal.floatVal = prevVal.floatVal + operand;
} while(atomic_cmpxchg((volatile local unsigned int *)source, prevVal.intVal, newVal.intVal) != prevVal.intVal)
After removing qualifiers (for simplicity) and renaming parameters, the signature of atomic_cmpxchg is the following:
int atomic_cmpxchg(int *ptr, int expected, int new)
What it does is:
atomically {
int old = *ptr;
if (old == expected) {
*ptr = new;
}
return old;
}
To summarize, each thread, individually, does:
Load current value of *source from memory into preVal.floatVal
Compute desired value of *source in newVal.floatVal
Execute the atomic compare-exchange described above (using the type-punned values)
If the result of atomic_cmpxchg == newVal.intVal, it means the compare-exchange was successful, break. Otherwise, the exchange didn't happen, go to 1 and try again.
The above loop eventually terminates, because eventually, each thread succeeds in doing their atomic_cmpxchg.
Can we say that each work-item has a mutex access (I mean a locked access) to value located at source address.
Mutexes are locks, while this is a lock-free algorithm. OpenCL can simulate mutexes with spinlocks (also implemented with atomics) but this is not one.

Will an array of pointers be equal to an array of chars?

I have got this code:
import std.stdio;
import std.string;
void main()
{
char [] str = "aaa".dup;
char [] *str_ptr;
writeln(str_ptr);
str_ptr = &str;
*(str_ptr[0].ptr) = 'f';
writeln(*str_ptr);
writeln(str_ptr[0][1]);
}
I thought that I am creating an array of pointers char [] *str_ptr so every single pointer will point to a single char. But it looks like str_ptr points to the start of the string str. I have to make a decision because if I am trying to give access to (for example) writeln(str_ptr[1]); I am getting a lot of information on console output. That means that I am linking to an element outside the boundary.
Could anybody explain if it's an array of pointers and if yes, how an array of pointers works in this case?
What you're trying to achieve is far more easily done: just index the char array itself. No need to go through explicit pointers.
import std.stdio;
import std.string;
void main()
{
char [] str = "aaa".dup;
str[0] = 'f';
writeln(str[0]); // str[x] points to individual char
writeln(str); // faa
}
An array in D already is a pointer on the inside - it consists of a pointer to its elements, and indexing it gets you to those individual elements. str[1] leads to the second char (remember, it starts at zero), exactly the same as *(str.ptr + 1). Indeed, the compiler generates that very code (though plus range bounds checking in D by default, so it aborts instead of giving you gibberish). The only note is that the array must access sequential elements in memory. This is T[] in D.
An array of pointers might be used if they all the pointers go to various places, that are not necessarily in sequence. Maybe you want the first pointer to go to the last element, and the second pointer to to the first element. Or perhaps they are all allocated elements, like pointers to objects. The correct syntax for this in D is T*[] - read from right to left, "an array of pointers to T".
A pointer to an array is pretty rare in D, it is T[]*, but you might use it when you need to update the length of some other array held by another function. For example
int[] arr;
int[]* ptr = &arr;
(*ptr) ~= 1;
assert(arr.length == 1);
If ptr wasn't a pointer, the arr length would not be updated:
int[] arr;
int[] ptr = arr;
ptr ~= 1;
assert(arr.length == 1); // NOPE! fails, arr is still empty
But pointers to arrays are about modifying the length of the array, or maybe pointing it to something entirely new and updating the original. It isn't necessary to share individual elements inside it.

QMap Memory Error

I am doing one project in which I define a data types like below
typedef QVector<double> QFilterDataMap1D;
typedef QMap<double, QFilterDataMap1D> QFilterDataMap2D;
Then there is one class with the name of mono_data in which i have define this variable
QFilterMap2D valid_filters;
mono_data Scan_data // Class
Now i am reading one variable from a .mat file and trying to save it in to above "valid_filters" QMap.
Qt Code: Switch view
for(int i=0;i<1;i++)
{
for(int j=0;j<1;j++)
{
Scan_Data.valid_filters[i][j]=valid_filters[i][j];
printf("\nValid_filters=%f",Scan_Data.valid_filters[i][j]);
}
}
The transferring is done successfully but then it gives run-time error
Windows has triggered a breakpoint in SpectralDataCollector.exe.
This may be due to a corruption of the heap, and indicates a bug in
SpectralDataCollector.exe or any of the DLLs it has loaded.
The output window may have more diagnostic information
Can anyone help in solving this problem. It will be of great help to me.
Thanks
Different issues here:
1. Using double as key type for a QMap
Using a QMap<double, Foo> is a very bad idea. the reason is that this is a container that let you access a Foo given a double. For instance:
map[0.45] = foo1;
map[15.74] = foo2;
This is problematic, because then, to retrieve the data contained in map[key], you have to test if key is either equal, smaller or greater than other keys in the maps. In your case, the key is a double, and testing if two doubles are equals is not a "safe" operation.
2. Using an int as key while you defined it was double
Here:
Scan_Data.valid_filters[i][j]=valid_filters[i][j];
i is an integer, and you said it should be a double.
3. Your loop only test for (i,j) = (0,0)
Are you aware that
for(int i=0;i<1;i++)
{
for(int j=0;j<1;j++)
{
Scan_Data.valid_filters[i][j]=valid_filters[i][j];
printf("\nValid_filters=%f",Scan_Data.valid_filters[i][j]);
}
}
is equivalent to:
Scan_Data.valid_filters[0][0]=valid_filters[0][0];
printf("\nValid_filters=%f",Scan_Data.valid_filters[0][0]);
?
4. Accessing a vector with operator[] is not safe
When you do:
Scan_Data.valid_filters[i][j]
You in fact do:
QFilterDataMap1D & v = Scan_Data.valid_filters[i]; // call QMap::operator[](double)
double d = v[j]; // call QVector::operator[](int)
The first one is safe, and create the entry if it doesn't exist. The second one is not safe, the jth element in you vector must already exist otherwise it would crash.
Solution
It seems you in fact want a 2D array of double (i.e., a matrix). To do this, use:
typedef QVector<double> QFilterDataMap1D;
typedef QVector<QFilterDataMap1D> QFilterDataMap2D;
Then, when you want to transfer one in another, simply use:
Scan_Data.valid_filters = valid_filters;
Or if you want to do it yourself:
Scan_Data.valid_filters.clear();
for(int i=0;i<n;i++)
{
Scan_Data.valid_filters << QFilterDataMap1D();
for(int j=0;j<m;j++)
{
Scan_Data.valid_filters[i] << valid_filters[i][j];
printf("\nValid_filters=%f",Scan_Data.valid_filters[i][j]);
}
}
If you want a 3D matrix, you would use:
typedef QVector<QFilterDataMap2D> QFilterDataMap3D;

Resources