Not understand struct Barnyard2's sf_ip header file - c

I am looking at Barnyard2's sf_ip.h source code. I am not understanding the sfip_t stuct, particulary the union block.
typedef struct _ip {
int family;
int bits;
/* see sfip_size(): these address bytes
* must be the last field in this struct */
union
{
u_int8_t u6_addr8[16];
u_int16_t u6_addr16[8];
u_int32_t u6_addr32[4];
// u_int64_t u6_addr64[2];
} ip;
#define ip8 ip.u6_addr8
#define ip16 ip.u6_addr16
#define ip32 ip.u6_addr32
// #define ip64 ip.u6_addr64
} sfip_t;
Why is it using arrays? I tried to look for documentation but Google has been of no luck. Can anyone explain what is being done here please?

A union in C uses the same memory block for all its elements. This is distinct from a structure, in which the elements are consecutive in memory.
So, while struct {int x; int y;} would be laid out thus if your variable started at memory location 0x40000000:
+-------------+
0x40000000 | x (4 bytes) |
+-------------+
0x40000004 | y (4 bytes) |
+-------------+
a related union {int x; int y;} exists like this:
Address
+-------------+-------------+
0x40000000 | x (4 bytes) | y (4 bytes) |
+-------------+-------------+
In other words, it can only be used for one thing at a time and, technically, it's undefined behaviour to use y when you last used x to set the variable - though in this case, you'll most likely find it will work since the two possibilities are the same type.
In your particular case, you have the following memory layout (assuming your variable was located at 0x40000000):
+--------------+--------------+--------------+
0x40000000 | u6_addr8[ 0] | | |
+--------------+ u6_addr16[0] | |
0x40000001 | u6_addr8[ 1] | | |
+--------------+--------------+ u6_addr32[0] |
0x40000002 | u6_addr8[ 2] | | |
+--------------+ u6_addr16[1] | |
0x40000003 | u6_addr8[ 3] | | |
+--------------+--------------+--------------+
0x40000004 | u6_addr8[ 4] | | |
+--------------+ u6_addr16[2] | |
0x40000005 | u6_addr8[ 5] | | |
+--------------+--------------+ u6_addr32[1] |
0x40000006 | u6_addr8[ 6] | | |
+--------------+ u6_addr16[3] | |
0x40000007 | u6_addr8[ 7] | | |
+--------------+--------------+--------------+
0x40000008 | u6_addr8[ 8] | | |
+--------------+ u6_addr16[4] | |
0x40000009 | u6_addr8[ 9] | | |
+--------------+--------------+ u6_addr32[2] |
0x4000000a | u6_addr8[10] | | |
+--------------+ u6_addr16[5] | |
0x4000000b | u6_addr8[11] | | |
+--------------+--------------+--------------+
0x4000000c | u6_addr8[12] | | |
+--------------+ u6_addr16[6] | |
0x4000000d | u6_addr8[13] | | |
+--------------+--------------+ u6_addr32[3] |
0x4000000e | u6_addr8[14] | | |
+--------------+ u6_addr16[7] | |
0x4000000f | u6_addr8[15] | | |
+--------------+--------------+--------------+
Assuming you understand how your particular C implementation lays out various types, this provides a way to reference the same data in different ways.

Related

viewing the variable stored in an C array [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 months ago.
The community is reviewing whether to reopen this question as of 5 months ago.
Improve this question
I am making a code that reads the data every time a new frequency is applied.
(I have a list of frequencies in an array)
I would like to display at the start of the set of readings a text saying current frequency (Hz): and then the value defined in the following array int freq[] = {1000 , 10000 , 30000 } . I am indexing the different frequencies in a for loop with the following code
for (byte count = 0; count < 6; count = count + 1) {
Serial.print("current Frequency(hz): ");
Serial.println( freq[count], 4);
However when I open the serial monitor I get numbers that I have not defined as a in the freq array. What am I doing wrong.
It takes the 4 least significant bits of cmd and the 10 least significant bits of data and combines them as follows:
cmd data
+---+---+---+---+---+ +---+---+---+---+---+---+---+---+---+---+---+
... | | | | | ... | | | | | | | | | | |
+---+---+---+---+---+ +---+---+---+---+---+---+---+---+---+---+---+
| | | | | | | | | | | | | |
| | | +---------+ | | | | | | | | | |
| | +---------+ | | | | | | | | | | |
| +---------+ | | | | | | | | | | | |
+---------+ | | | | | | | | | | | | |
| | | | | | | | | | | | | |
v v v v v v v v v v v v v v
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| 0 | 0 | | | | | | | | | | | | | | |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
data_word

Valgrind warns of overlap when trying to copy a string into a struct member variable

This is how the struct looks like for reference:
struct thread_data {
struct ringbuf_t *rb;
char *file_name;
};
I need to take command line arguments and store it inside struct member variables for each thread_data element in the threads array, like so:
for (int index = optind; index < argc; index++) {
threads[length].rb = rb;
memmove(&threads[length].file_name, &argv[index], strlen(argv[index]));
strcpy(threads[length].file_name, argv[index]);
++length;
}
Prevously used memcpy and it worked when I printed the variable. However, Valgrind is giving me this:
==465645== Source and destination overlap in strcpy(0x1fff000b54, 0x1fff000b54)
==465645== at 0x4C3C180: strcpy (vg_replace_strmem.c:523)
==465645== by 0x400F85: main (bytemincer.c:55)
So I used memmove and I still got the same Valgrind result. Any solution for this?
This is what you want to end up with:
(I'm using "fn" instead of "file_name" in the post.)
*(argv[0]) # 0x2000
+---+---+- -+---+
+--------------->| | | … | 0 |
argv # 0x1000 | +---+---+- -+---+
+---------------+ |
| 0x2000 -------+ *(argv[1]) # 0x2100
+---------------+ +---+---+- -+---+
| 0x2100 -----------+----------->| | | … | 0 |
+---------------+ | +---+---+- -+---+
| 0x2200 -----------)----+
+---------------+ | | *(argv[2]) # 0x2200
| ⋮ | | | +---+---+- -+---+
| +------->| | | … | 0 |
rb # 0x3000 | | +---+---+- -+---+
+---------------+ | |
| 0x4000 -------+ | | *rb # 0x4000
+---------------+ | | | +---------------+
+---)---)------->| |
threads # 0x5000 | | | +---------------+
+---------------+ | | |
| +-----------+| | | |
|rb| 0x4000 --------+ | |
| +-----------+| | | |
|fn| 0x2100 --------)---+ |
| +-----------+| | |
+---------------+ | |
| +-----------+| | |
|rb| 0x4000 --------+ |
| +-----------+| |
|fn| 0x2200 ----------------+
| +-----------+|
+---------------+
| ⋮ |
(This assumes threads is an array rather than a pointer to an array. This doesn't affect the rest of the post.)
All addresses are made up, of course. But you can see how more than once variable have the same address for value. Because it's perfectly fine to have multiple pointers point to the same memory block. All we need to do is copy the pointer (the address).
To copy a pointer, all you need to do is
dst = src;
So all you need is
threads[length].rb = rb;
threads[length].fn = argv[index];
While
memmove(&threads[length].rb, &rb, sizeof(threads[length].rb));
memmove(&threads[length].fn, &argv[index], sizeof(threads[length].fn));
and
memmove(&threads[length].rb, &rb, sizeof(rb));
memmove(&threads[length].fn, &argv[index], sizeof(argv[index]));
are equivalent to the assignments, it doesn't make sense to do something that complicated:
(Note the use of sizeof(argv[index]) rather than strlen(argv[index]). It's the pointer we're copying, so we need the size of the pointer.)
The warning came from trying to copy the string that's in the buffer at 0x2100 into the buffer at 0x2100. Remember that threads[length].fn and argv[index] both have the same value (address) after the memmove.

why `execv` can't use implicit convert from char** to char* const*?

Consider the following code:
#include <stdio.h>
#include <unistd.h>
void foo(char * const arg[]) {
printf("success\n");
}
int main() {
char myargs[2][64] = { "/bin/ls", NULL };
foo(myargs);
execv(myargs[0], myargs);
return 0;
}
Both foo and execv require char * const * argument, but while my foo works (I get success in the output) the system call execv fails.
I would like to know why. Does this have something to do with the implementation of execv?
Also, assuming I have a char** variable - how can I send it to execv?
A two-dimensional array looks like this:
char myargs[2][16];
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| | | | | | | | | | | | | | | | |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| | | | | | | | | | | | | | | | |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
I reduced the size from 64 to 16 to keep the diagram from being annoyingly big.
With an initializer, it can look like this:
char myargs[2][16] = { "/bin/ls", "" }
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| /| b| i| n| /| l| s|\0| | | | | | | | |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|\0| | | | | | | | | | | | | | | |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
Notice I didn't try to put a null pointer in the second row. It doesn't make sense to do that, since that's an array of chars. There's no place in it for a pointer.
The rows are contiguous in memory, so if you look at a lower level, it's actually more like this:
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| /| b| i| n| /| l| s|\0| | | | | | | | |\0| | | | | | | | | | | | | | | |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
When you pass myargs to a function, the famous "array decay" produces a pointer. That looks like this:
void foo(char (*arg)[16]);
...
char myargs[2][16] = { "/bin/ls", "" }
foo(myargs);
+-----------+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| POINTER==|===>| /| b| i| n| /| l| s|\0| | | | | | | | |\0| | | | | | | | | | | | | | | |
+-----------+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
The pointer is arg contains a value which locates the beginning of the array. Notice there is no pointer pointing to the second row. If foo wants to find the value in the second row, it needs to know how big the rows are so it can break down this:
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| /| b| i| n| /| l| s|\0| | | | | | | | |\0| | | | | | | | | | | | | | | |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
into this:
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| /| b| i| n| /| l| s|\0| | | | | | | | |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|\0| | | | | | | | | | | | | | | |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
That's why arg must be char (*arg)[16] and not char **arg or the equivalent char *arg[].
The exec family of functions doesn't work with this data layout. It wants this:
+-----------+ +-----------+-----------+
| POINTER==|===>| POINTER | NULL |
+-----------+ +-----|-----+-----------+
|
/----------------------/
|
|
| +--+--+--+--+--+--+--+--+
\--->| /| b| i| n| /| l| s|\0|
+--+--+--+--+--+--+--+--+
And when you want to add more arguments, it wants this:
+-----------+ +-----------+-----------+- -+-----------+
| POINTER==|===>| POINTER | POINTER | ... | NULL |
+-----------+ +-----|-----+-----|-----+- -+-----------+
| |
/----------------------/ |
| |
| /--------------------------------/
| |
| |
| | +--+--+--+--+--+--+--+--+
\-+->| /| b| i| n| /| l| s|\0|
| +--+--+--+--+--+--+--+--+
|
| +--+--+--+--+--+--+
\->| /| h| o| m| e|\0|
+--+--+--+--+--+--+
If you compare this to the two-dimensional array diagram, hopefully you can understand why this can't be an implicit conversion. It actually involves moving stuff around in memory.
Both foo and execv require char * const * argument,
Yes.
but while my foo works (I get success in the output) the system call execv fails.
Getting the output you expect does not prove that your code is correct. The call exhibits undefined behavior because its argument does not match the parameter type, but it is plausible that that has little practical effect because the implementation of foo() does not use the parameter in any way. More generally, your code could, in principle, exhibit absolutely any behavior at all, because that's what "undefined" means.
I would like to know why. Does this have something to do with the implementation of execv?
From the standard's perspective, both calls exhibit equally undefined behavior. As a practical matter, however, we know that execv does use its arguments, so it would be much more surprising for that call to produce the behavior you expected than it is for the call to foo to produce the behavior you expected.
The main problem is that 2D arrays are arrays of arrays, and arrays are not pointers. Thus, your 2D array myargs does not at all have the correct type for an argument to either function.
Also, assuming I have a char** variable - how can I send it to execv?
You do not have such a variable in your code, but if you did have, you could cast it to the appropriate type:
char *some_args[] = { "/bin/ls", NULL };
execv((char * const *) some_args);
In practice, most compilers would probably accept it if you omitted the cast, too, although the standard does require it. Best would be to declare a variable that has the correct type in the first place:
char * const correct_args[] = { "/bin/ls", NULL };
execv(correct_args);
Note also that although arrays are not pointers, they are converted to pointers in most contexts -- which I use in the example code -- but only the top level. An array of arrays thus "decays" to a pointer to an array, not a pointer to a pointer.

How to interpret sybase RESTRICT Operator (VA = 1)(4)(0)(0)(0)(0)

Can someone help to clarify restrict operator?
I understand Sybase restrict operator is used to evaluate expressions based on columns. But I still can't figure out the exact meaning of RESTRICT Operator in the query plan.
e.g, below is a query plan snippet of my sql. RESTRICT Operator (VA = 1)(4)(0)(0)(0)(0): what does (4)(0)(0)(0)(0) mean?
10 operator(s) under root
|ROOT:EMIT Operator (VA = 10)
|
| |SCALAR AGGREGATE Operator (VA = 9)
| | Evaluate Ungrouped COUNT AGGREGATE.
| |
| | |N-ARY NESTED LOOP JOIN Operator (VA = 8) has 7 children.
| | |
| | | |RESTRICT Operator (VA = 1)(4)(0)(0)(0)(0)
| | | |
| | | | |SCAN Operator (VA = 0)
| | | | | FROM TABLE
| | | | | trade
| | | | | t
| | | | | Index : i1
| | | | | Forward Scan.
| | | | | Positioning by key.
| | | | | Keys are:
| | | | | order_number ASC
| | | | | Using I/O Size 16 Kbytes for index leaf pages.
| | | | | With LRU Buffer Replacement Strategy for index leaf pages.
| | | | | Using I/O Size 16 Kbytes for data pages.
| | | | | With LRU Buffer Replacement Strategy for data pages.
| | |
| | | |SCAN Operator (VA = 2)
| | | | FROM TABLE
| | | | product
| | | | mp
| | | | Index : mp
| | | | Forward Scan.
| | | | Positioning by key.
| | | | Keys are:
| | | | prod_id ASC
| | | | Using I/O Size 16 Kbytes for index leaf pages.
| | | | With LRU Buffer Replacement Strategy for index leaf pages.
| | | | Using I/O Size 16 Kbytes for data pages.
| | | | With LRU Buffer Replacement Strategy for data pages.
| | |
| | | |SCAN Operator (VA = 3)
| | | | FROM TABLE
| | | | Accounts
| | | | a
| | | | Index : i2
| | | | Forward Scan.
| | | | Positioning by key.
| | | | Index contains all needed columns. Base table will not be read.
| | | | Keys are:
| | | | account ASC
| | | | Using I/O Size 16 Kbytes for index leaf pages.
| | | | With LRU Buffer Replacement Strategy for index leaf pages.
Part of the showplan output, like those numbers behind the operator, are internals of the ASE optimizer. There is no documented information about these, and this information is included to help techsupport in resolving issues.
The 'VA = n' part is just reflecting the unique number 'n' for every operator in the query plan.

Understanding to convert a multi-dimensional array to a one-dimensional array

There is a really good explanation of multi-dimensional array here on stackoverflow which I have studied and researched but i have few follow up questions for anyone who wants to help out. This is not a HW question, it is out of my text book which I am trying to understand more so please confirm if I am looking at the below example correctly. Thank you in advance.
So if i had a 3 dimensional array such as this:
{{{'1','2'},{'3','4'}},
{{'5','6'},{'7','8'}},
{{'9','10'},{'11','12'}}};
Would the one dimensional outcome (using c compiler) simply be?:
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| | | | | | | | | | | | |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
And the corresponding position as?
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| | | | | | | | | | | | |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
Again I am using this link as my source.
The only thing I am looking for as a form of answer is, am I looking/doing this correctly? If not, I would appreciate it if you can tell me where I have made any mistakes. Thank you again.
1.
char [3][2][2] :
+-----+-----+ +-----+-----+
|+-----+-----+ |+-----+-----+
|| 1 | 3 | || 4 | 5 |
||1,0+-----+-----+ || +-----+-----+
|+---| a | b | |+---| 0 | 1 |
|| 2|0,0,0|0,0,1| || 6| | |
+|1,1+-----+-----+ => +| +-----+-----+
+---| x | y | +---| 2 | 3 |
|0,1,0|0,1,1| | | |
+-----+-----+ +-----+-----+
so your outcome seems ok, and thus (2.) t3[0] should be a.
2.
if t2 looks like this, t2[0][1] is b:
+-----+-----+-----+-----+ +-----+-----+-----+-----+
| a | b | x | y | | | | | |
|0,0,0|0,0,1|0,1,0|0,1,1| | 0,0 | 0,1 | 0,2 | 0,3 |
+-----+-----+-----+-----+ +-----+-----+-----+-----+
| 1 | 3 | 2 | 7 | => | | | | |
|1,0,0|1,0,1|1,1,0|1,1,1| | 1,0 | 1,1 | 1,2 | 1,3 |
+-----+-----+-----+-----+ +-----+-----+-----+-----+
| q | g | r | 4 | | | | | |
|2,0,0|2,0,1|2,1,0|2,1,1| | 2,0 | 2,1 | 2,2 | 2,3 |
+-----+-----+-----+-----+ +-----+-----+-----+-----+
As long you are converting them the right way(as it seems according to the link) it should work...
For conceptual understanding this is a good starting point.
But you should understand the difference between row vs column major. And technically it could vary between compilers and languages depending upon what they are designed for.
http://en.wikipedia.org/wiki/Row-major_order

Resources