Double pointer **src and operation (*(*src)++ = reg_offset) - c++

I'm newer in C/C++, I really confuse about a function that executes complex operation. I just want to know how it works ? What does function mean ?
void writetoXX(unsigned int **src, unsigned int reg_offset, unsigned int reg_data){
*(*src)++ = reg_offset;
*(*src)++ = reg_data;
}
Any idea ??
Update my understanding:
void writetoXX(unsigned int **src, unsigned int reg_offset, unsigned int reg_data) {
*(*src)++ = reg_offset;
*(*src)++ = reg_data;
}
int main() {
int a[10] = { 0 };
int *p = a;
printf("Before !!\n");
for(int i=0;i<10;i++)
printf("%d ", a[i]);
writetoXX(&p, 20, 30);
printf("After !!! \n");
for (int i = 0; i<10; i++)
printf("%d ", a[i]);
getchar();
return 0;
}
After run this program, I see that the function writetoXX change value arr[0][0] and arr[0][1] to 20 and 30. It means that the function is used for write data to 2 consecutive blocks.
And output is below:
Before !!
0 0 0 0 0 0 0 0 0 0
After !!
20 30 0 0 0 0 0 0 0 0

src is a pointer to a pointer to an unsigned int, for example this is used for bidimensional arrays. Because of the operator precedence, the routine does:
take *src, it is a pointer to an unsigned int
(*src)++ increments the pointer, such that it points to the next unsigned int. It is a post increment, so it returns the value before the increment.
*(*src)++ is the unsigned int pointed by *src before the increment ++
So in summary, you take * src which is a pointer to unsigned int, you assign the first pointed data to reg_offset, then you increment such pointer, then you assign the next element to reg_data, and finally you increment again the pointer *src.

Double pointer is a variable which stores address of another pointer variable.
Consider this *(*src)++ = reg_offset;
In one line: The value of reg_offset is stored at current address stored in src and the address in src is incremented.
You can consider this happening in the following order.
1) As you know src is a variable which is storing address of another pointer or memory space.
2) So (*src) whill give address of the pointed variable or memory space.
3) Due to operator precedence, (*src)++ takes place. Which you can read like, after executing the current line, increment the address value stored in src.
4) Now *(*src) Which is the memory space with address stored in (*src). So *(*src) = reg_offset; will copy the value of reg_offset to that address. I have removed ++ in this line just for clarity.
5) When the second line *(*src)++ = reg_data; is about to be executed, the (*src) will be pointing to next address. So reg_data is written to next address.
Please note, next address does not mean current_address+1. It actually means current_address+sizeof(data type). Ifunsigned int is 4 byte in your compiler, then next_address = current_address+4
You can print content of (*src) in between the lines and verify.

Related

C++ pointer and increment operator (++)

Recently, I begin to learn C++ language for Pointer series, I knew the pointer is the specific var what is used to hold the address of another variable. And when we change the value at the memory area which the pointer is hold, it also change the value of that var. So then i just wrote the code to do it.
#include <iostream>
#include <stdlib.h>
#include <time.h>
using namespace std;
int main(int argc, char const *argv[])
{
int n=5;
int *p=&n; //pointer p hold the address of n
std::cout<<"value of n = "<<n<<endl;
std::cout<<"value of n = "<<*p<<endl;
std::cout<<"value of n= "<<*(&n)<<endl;
std::cout<<"the address of n = "<<&n<<endl;
std::cout<<"the address of n = "<<p<<endl;
*p=19; //change the value at the address of n -> mean n definitely change
std::cout<<"value of n once *p changed = "<<n<<endl;
p++; //p address increase 4 bytes
std::cout<<"address of p changed = "<<p<<endl;
(*p)++;
std::cout<<"address of p = "<<p<<endl;
return 0;
}
then i got the resul below :
As I mark red in my picture, when I do (*p)++ - I understood that the value at the address p hold will increase 1, but once I check the result, it didn't show the value of p after (*p)++ line , just the address of p has increased 1 byte.
What is the reason for this?
If we break down your code into the important parts, we see:
int n=5; // 1.
int *p = &n; // 2.
p++; // 3.
(*p)++; // 4. Dereference and increment.
You clearly have a good grip on what 1-3 do in this code. But, 4 is a big problem. In 3, you changed the pointer. The pointer previously pointed to n, after incrementing, what does it point to now?Wherever it is, it is not necessarily memory that we own and can actively change.
In line 4, you change it. This is undefined behaviour which, from the linked page you can see:
undefined behavior - there are no restrictions on the behavior of the program.
So the program can do pretty much anything.
Your program has undefined behavior.
Let's look at this sequence picked from your program:
int n=5;
int *p=&n;
p++; // p now points to some unknown memory area
(*p)++; // here you dereference `p` - undefined behavior.
You are never allowed to dereference a pointer that is not pointing to an object that is "alive".

Why post increment to value of a variable by pointer variable (*variablePointer++) returns garbage value?

I'm just playing around pre/post increment/decrement in C language. In the program below, everything works fine with variable var. But increments to the pointer variable *varAddress++ return garbage value.
#include <stdio.h>
int main(int argc, const char * argv[])
{
int var = 1;
int *varAddress = &var;
printf("Value befor pre increment %d\n",*varAddress);
++*varAddress;
printf("Value after pre increment %d\n",*varAddress);
printf("Value befor post increment %d\n",*varAddress);
*varAddress++;
printf("Value after post increment %d\n",*varAddress);
return 0;
}
Output
Value befor pre increment 1
Value after pre increment 2
Value befor post increment 2
Value after post increment 1606416400
Program ended with exit code: 0
According to the Operator Precedence, suffix increment has higher precedence than indirection operator, so *varAddress++ is equivalent as:
*(varAddress++);
which will increase the pointer itself, then point to memory unallocated somewhere else, that's why *varAddress will return garbage value (this is UB).
You might want:
(*varAddress)++;
++ has higher precedence than * so by doing *varAddress++ you are moving a pointer to some un-owned location and trying to dereference it, which will lead to undefined behavior.
#include<stdio.h>
void main(){
char arr[] ="abcd";
char *p=arr,*q=arr;
char k,temp;
temp = *p++; /* here first it assigns value present in address which
is hold by p and then p points to next address.*/
k = ++*q;/*here increments the value present in address which is
hold by q and assigns to k and also stores the incremented value in the same
address location. that why *q will get 'h'.*/
printf("k is %c\n",k); //output: k is h
printf("temp is %c\n",temp);//output: temp is g
printf("*p is %c\n",*p);//output: *p is e
printf("*q is %c",*q);//output: *q is h
}

Working with Arrays in C

I am new to C and C++ and I need help with arrays. I have an array initialized to zero with 500 elements(myDataBinary). Now I have one more array ith values in it say 1,2,3....Now by reading the values (1,2,3...) from(my_data[10]) i want to make the corresponding elements in myDataBinary "1" and rest should be "0". I have written the below code to achieve this, but I am getting some segmentation fault and not able to see the proper results. Any help on this would be appreciated. Thanks in advance
int my_data[10] = {1,3,9,10};
int myDataBinary[500] = {0};
int index;
for(int i=0; i<sizeof(my_data);i++)
{
index = my_data[i];
myDataBinary[index] = 1;
printf("rec data %d = %d\n",index,myDataBinary[index]);
}
sizeof(my_data) returns the total size of the array in bytes, not the number of elements.
Since ints are (usually) 2 bytes wide, you're ending up outside the array.
Replace sizeof(my_data) in the for loop with sizeof(my_data)/sizeof(int) and try again.
sizeof operator gives the size of an object (or type) in bytes. The canonical way to determine the number of elements in an array x is:
sizeof x / sizeof x[0]
This does not depend upon knowing the type of the elements of x, and will work even if you change it. sizeof my_data / sizeof(int) doesn't have that property.
Note that my_data has to be an array, it cannot be a pointer. This is important because in many contexts (when passed to a function for example), the name of an array decays to a pointer, so the following "won't work":
void f(int *data)
{
printf("%zu\n", sizeof data);
}
int main(void)
{
int my_data[10] = {1,3,9,10};
printf("%zu\n", sizeof my_data);
f(my_data);
return 0;
}
The above program will print two different values (unless sizeof(int)*10 == sizeof(int *)).
Don't use sizeof(my_data) - this doesn't give you what you want. To find the number of the elements you can do int n = sizeof(my_data) / sizeof(int):
int my_data[10] = {1,3,9,10};
int myDataBinary[500] = {0};
int index;
int n = sizeof(my_data) / sizeof(int);
for(int i=0; i<n;i++)
{
index = my_data[i];
myDataBinary[index] = 1;
printf("rec data %d = %d\n",index,myDataBinary[index]);
}

Using pointer for crossing over all elements in INTEGER array

Is there a way to cross over all elements in integer array using pointer ( similiar to using pointer to cross over string elements).I know that integer array is not NULL terminated so when I try to cross over array using pointer it overflows.So I added NULL as a last element of an array and it worked just fine.
int array[7]={1,12,41,45,58,68,NULL};
int *i;
for(i=array;*i;i++)
printf("%d ",*i);
But what if one of the elements in array is 0 ,that will behave just as NULL.Is there any other way that will implement pointer in crossing over all elements in integer array?
In general, no unless you pick a sentinel value that's not part of the valid range of the data. For example, the valid range might be positive numbers, so you can use a negative number like -1 as a sentinel value that indicates the end of the array. This how C-style strings work; the NULL terminator is used because it's outside of the valid range of integers that could represent a character.
However, it's usually better to somehow pair up the array pointer with another variable that indicates the size of the array, or another pointer that points one-past-the-end of the array.
In your specific case, you can do something like this:
// Note that you don't have to specify the length of the array.
int array[] = {1,12,41,45,58,68};
// Let the compiler count the number of elements for us.
int arraySize = sizeof(array)/sizeof(int);
// or int arraySize = sizeof(array)/sizeof(array[0]);
int main()
{
int* i;
for(i = array; i != array + arraySize; i++)
printf("%d ",*i);
}
You can also do this:
int arrayBegin[] = {1,12,41,45,58,68};
int* arrayEnd = arrayBegin + sizeof(arrayBegin)/sizeof(arrayBegin[0]);
int main()
{
int* i;
for(i = arrayBegin; i != arrayEnd; i++)
printf("%d ",*i);
}
But given only a pointer, no you can't know how long the array it points to is. In fact, you can't even tell if the pointer points to an array or a single object! (At least not portably.)
If you have functions that must accept an array, either have your function require:
the pointer and the size of the array pointed by the pointer,
or two pointers with one pointing to the first element of the array and one pointing one-past-the-end of the array.
I'd like to give some additional advice: Never use some kind of sentinel/termination value in arrays for determining their bounds. This makes your programs prone to error and is often the cause for security issues. You should always store the length of arrays to limit all operations to their bounds and test against that value.
In C++ you have the STL and its containers.
In C you'll effectively end up using structures like
typedef struct t_int_array
{
size_t length;
int data[1]; /* note the 1 (one) */
} int_array;
and a set of manipulation functions like this
int_array * new_int_array(size_t length)
{
int_array * array;
/* we're allocating the size of basic t_int_array
(which already contains space for one int)
and additional space for length-1 ints */
array = malloc( sizeof(t_int_array) + sizeof(int) * (length - 1) );
if(!array)
return 0;
array->length = length;
return array;
}
int_array * concat_int_arrays(int_array const * const A, int_array const * const B);
int_array * int_array_push_back(int_array const * const A, int const value);
/* and so on */
This method will make the compiler align the t_int_array struct in a way, that it's optimal for the targeted architecture (also with malloc allocation), and just allocating more space in quantities of element sizes of the data array element will keep it that way.
The reason that you can iterate across a C-style string using pointers is that of the 256 different character values, one has been specifically reserved to be interpreted as "this is the end of the string." Because of this, C-style strings can't store null characters anywhere in them.
When you're trying to use a similar trick for integer arrays, you're noticing the same problem. If you want to be able to stop at some point, you'll have to pick some integer and reserve it to mean "this is not an integer; it's really the end of the sequence of integers." So no, there is no general way to take an array of integers and demarcate the end by a special value unless you're willing to pick some value that can't normally appear in the string.
C++ opted for a different approach than C to delineate sequences. Instead of storing the elements with some sort of null terminator, C++-style ranges (like you'd find in a vector, string, or list) store two iterators, begin() and end(), that indicate the first element and first element past the end. You can iterate over these ranges by writing
for (iterator itr = begin; itr != end; ++itr)
/* ... visit *itr here ... */
This approach is much more flexible than the C-string approach to defining ranges as it doesn't rely on specific properties of any values in the range. I would suggest opting to use something like this if you want to iterate over a range of integer values. It's more explicit about the bounds of the range and doesn't run into weird issues where certain values can't be stored in the range.
Apart from the usual suggestion that you should go and use the STL, you can find the length of a fixed array like this:
int array[6]={1,12,41,45,58,68};
for (int i = 0; i < sizeof(array) / sizeof(array[0]); ++i)
{ }
If you use a templated function, you can implicitly derive the length like this:
template<size_t len> void func(int (&array)[len])
{
for (int i = 0; i < len; ++i) { }
}
int array[6]={1,12,41,45,58,68};
func(array);
If 0 is a value that may occur in a normal array of integers, you can specify a different value:
const int END_OF_ARRAY = 0x80000000;
int array[8]={0,1,12,41,45,58,68,END_OF_ARRAY};
for (int i = 0; array[i] != END_OF_ARRAY; ++i)
{ }
If every value is a possibility, or if none of the other approaches will work (for example, a dynamic array) then you have to manage the length separately. This is how strings that allow embedded null characters work (such as BSTR).
In your example you are using (or rather abusing) the NULL macro as a sentinel value; this is the function of the NUL('\0') character in a C string, but in the case of a C string NUL is not a valid character anywhere other than as the terminal (or sentinel) value .
The NULL macro is intended to represent an invalid pointer not an integer value (although in C++ when implicitly or explicitly cast to an int, its value is guaranteed to be zero, and in C this is also almost invariably the case). In this case if you want to use zero as the sentinel value you should use a literal zero not NULL. The problem is of course that if in this application zero is a valid data value it is not suitable for use as a sentinel.
So for example the following might suit:
static const int SENTINEL_VALUE = -1 ;
int array[7] = { 1, 12, 41, 45, 58, 68, SENTINEL_VALUE } ;
int* i ;
for( i = array; *i != SENTINEL_VALUE; i++ )
{
printf( "%d ", *i ) ;
}
If all integer values are are valid data values then you will not be able to use a sentinel value at all, and will have to use either a container class (which knows its length) or iterate for the known length of the array (from sizeof()).
Just to pedanticize and expand a little on a previous answer: in dealing with integer arrays in C, it's vanishingly rare to rely on a sentinel value in the array itself. No(1) sane programmer does that. Why not? Because by definition an integer can hold any value within predefined negative/positive limits, or (for the nowadays-not-unusual 32-bit integer) 0 to 0xffffff. It's not a good thing to redefine the notion of "integer" by stealing one of its possible values for a sentinel.
Instead, one always(1) must(1) rely on a controlling up-to-date count of integers that are in the array. Suppose we are to write a C function
that returns an int pointer to the first array member whose value is greater than the function's argument or, if there's no such member, returns NULL (all code is untested):`
int my_int_array[10]; // maximum of 10 integers in my_int_array[], which must be static
int member_count = 0; // varies from 0 to 10, always holds number of ints in my_int_array[]
int *
first_greater_than ( int val ) {
int i;
int *p;
for ( i = 0, p = my_int_array; i < member_count; ++i, ++p ) {
if ( *p > val ) {
return p;
}
}
return NULL;
}
Even better is also to limit the value of i to never count past the last possible member of my_int_array[], i.e., it never gets bigger than 9, and p never points at my_int_array[10] and beyond:
int my_int_array[10]; // maximum of 10 integers in my_int_array[], which must be static
int member_count = 0; // varies from 0 to 10, always holds number of ints in my_int_array[]
int *
first_greater_than ( int val ) {
#define MAX_COUNT sizeof(my_int_array)/sizeof(int)
int i;
int* p;
for ( i = 0, p = my_int_array; i < member_count && i < MAX_COUNT; ++i, ++p ) {
if ( *p > val ) {
return p;
}
}
return NULL;
}
HTH and I apologize if this is just too, too elementary.
--pete
Not strictly true but believe it for now
In ANSI C it's very easy and shorter than solution before:
int array[]={1,12,41,45,58,68}, *i=array;
size_t numelems = sizeof array/sizeof*array;
while( numelems-- )
printf("%d ",*i++);
Another way is to manage array of pointers to int:
#include <stdlib.h>
#include <stdio.h>
#define MAX_ELEMENTS 10
int main() {
int * array[MAX_ELEMENTS];
int ** i;
int k;
// initialize MAX_ELEMENTS,1 matrix
for (k=0;k<MAX_ELEMENTS;k++) {
array[k] = malloc(sizeof(int*));
// last element of array will be NULL pointer
if (k==MAX_ELEMENTS-1)
array[k] = NULL;
else
array[k][0] = k;
}
// now loop until you get NULL pointer
for (i=array;*i;i++) {
printf("value %i\n",**i);
}
// free memory
for (k=0;k<MAX_ELEMENTS;k++) {
free(array[k]);
}
return 0;
}
In this way loop condition is totally independent from the values of integers. But... for this to work you must use 2D array (matrix) instead of ordinary 1D array. Hope that helps.

testing for valid pointer in c++

I wrote a little test to check for null pointer, I simplified it with int and 0, 1, instead of real classes, what I'm trying to test is something like this: return p ? 1 : 0;
which in real world would be return p ? p->callmethod() : 0;
bool TestTrueFalse();
void main()
{
int i = TestTrueFalse();
}
bool TestTrueFalse()
{
int one = 1;
int * p =&one;
*p = 0;
return p ? 1 : 0;
}
now, you can see, that once the pointer becomes 0 again, the test fails, why?
what's wrong with this? what's the solution?
*p = 0;
you probably meant
p = 0;
*p = 0 sets what the pointer points to, not the pointer
When testing a pointer value with a conditional in C++, it will return true if the value is non-zero and false if the value is 0. In your sample p is slated to point at the local one and hence has a non-zero address (even though the value at the address is 0). Hence you get true
A null pointer is a pointer which points to the address 0, not the value 0.
To set a pointer to null, do:
p = 0;
To elaborate, your code sets the pointed-to-int to 0. For example:
int i = 1;
int *p = &i;
assert(*p == 1); //p points to 1
*p = 0;
assert(*p == 0 && i == 0); //p points to the same location, but that location now contains 0
The code *p = 0; does not set the pointer to null. It sets what p is pointing to zero.
A pointer is an address in memory. int *p = &one; takes the address of the variable one, and stores it in p. *p = 0; stores 0 in the memory pointed to by p, meaning that the value of one is now 0. So, you have changed what p points to, but not p itself. TestTrueFalse() will return 1.
to test it for a null pointer before inspecting the value pointed to you might use code like
if(ip != NULL)
taken from http://www.eskimo.com/~scs/cclass/notes/sx10d.html
NULL might be safer in your code, as it is more compiler independent than just writing 0. and it might also be more clear for others to read in your code.