Structured Text - dereference table pointer with offset - structured-text

Regarding the Structured Text Programming Language:
If I have a pointer to a table:
crcTable : ARRAY [0..255] OF WORD;
pcrcTable : POINTER TO WORD;
pcrcTable := ADR(crcTable);
and I want dereference the table at a certain index, what is the syntax to do so? I think the equivalent C code would be:
unsigned short crcTable[256];
unsigned short* pcrcTable = &crcTable[0];
dereferencedVal = pcrcTable[50]; //Grab table value at index = 50

You need to first move the pointer according to the array index that you want to get to. And then do the dereferencing.
// Dereference index 0 (address of array)
pcrcTable := ADR(crcTable);
crcVal1 := pcrcTable^;
// Dereference index 3 (address of array and some pointer arithmetic)
pcrcTable := ADR(crcTable) + 3 * SIZEOF(pcrcTable^);
crcVal2 := pcrcTable^;
// Dereference next index (pointer arithmetic)
pcrcTable := pcrcTable + SIZEOF(pcrcTable^);
crcVal3 := pcrcTable^;

Related

C++ expression is not assignable when writing `&str_send[0] = &str_recv[c * 6];`

I'm trying to parse an array that receives a multiple of 8 bytes and sends back each array of 8 bytes one at a time.
I'm getting an expression is not assignable or lvalue required as left operand of assignment error when building
I'm trying to figure out why I cannot simply change the address of an array to the new position. At first I thought it was a C-style array issue, but the same error happened when I tried with std::vector<unsigned char>
Is there a preferable way of doing this without copying the bytes?
Thanks,
unsigned char str_send[8];
unsigned char str_recv[BUF_SIZE];
int n = receive(cport_nr, str_recv, (int)BUF_SIZE);
if (n > 0 && ( n % 8 == 0 ) )
{
for (int c = 0; c < n / 8; c++) //Break up multiple 8-byte chunks
{
&str_send[0] = &str_recv[c * 6]; //ERROR expression is not assignable
}
}
return (0);
You can't change the address of a variable.
What you could do is create an array of pointers to the original array, but then you're just copying addresses (probably 8 bytes each) instead of single byte values. Then you've have to dereference those pointers, which makes it non-trivial to send what they point to.
Copying the bytes is exactly what you want to do here. Then you have a buffer you can send as-is:
str_send[0] = str_recv[c * 6];

VB.NET error "Value of type 'Ushort' cannot be converted to 'Ushort()'" reading two-dimensional array of bytes from a native C++ DLL

I'm getting VB error: "Value of type 'Ushort' cannot be converted to 'Ushort()'".
I have a VB.NET windows app that calls a function in a native (C++) DLL, to read a specific 256 byte page from an array of the pages within the DLL.
VISUAL-C++ declaration within the DLL source, of the function....
extern "C" BASICDLL_API int __stdcall My_Read_High_Speed_Data(unsigned char ptr, unsigned short *buf)
{
return BDLL_ReadBlock(0x00300000 + ptr, (unsigned char *)buf);
}
VB.NET Declaration of the function in the DLL................
<DllImport("MyDll.dll", CallingConvention:=CallingConvention.Cdecl, CharSet:=CharSet.Ansi)>
Public Function My_Read_Parameters(ByVal board As Byte, ByVal params As UShort()) As Int32
End Function
Declaration of the VB.NET buffer to hold the 64 pages of 256 bytes each, from DLL...............
Dim input_page_buffer( 64, 256 ) As UInt16
VB.NET function to read the page from the DLL...................
function poll()
dim page_index = 1
dim success = My_Read_High_Speed_Data( page_index, input_page_buffer(1, 1) )
end function
The dll import function
..., ByVal params As UShort()
calls for a UShort() as the second argument, while the c++ has
..., unsigned short *buf)
Change the dll import to UShort
After reading the question properly ( :) ) I think I understand what you're trying to do... The C++ function is expecting a byte array for its buf parameter, which is then filled with 256 bytes by the BDLL_ReadBlock() function.
Why you have declared the parameter as unsigned short* rather than unsigned byte* I don't understand, since BDLL_ReadBlock() clearly expects the latter.
Anyway, to fix the issue you would have to switch from a two-dimensional array to a jagged array. This is because they do different things:
In a two-dimensional array you have all items laid out in a grid, pretty much like a fixed coordinate system:
Array(3, 3):
0 1 2 3
0 A B C D
1 E F G H
2 I J K L
3 M N O P
However, a jagged array is an array of arrays, which means you have a set of columns and rows where the columns doesn't necessarily have to be of the same amount for every row:
Array(3)(3):
0 1 2 3
0 {A, B, C, D}
1 {E, F, G, H}
2 {I, J, K, L}
3 {M, N, O, P}
Array(3)(x):
0 1 2 3 4
0 {A, B}
1 {C, D, E, F, G}
2 {H, I, J}
3 {K}
The difference when accessing items is that in a 2D array you can only get ONE item at a time:
Array(1, 3) = H
...whereas in a jagged array you don't necessarily have to access only one item, but you can also reference an entire row:
'Single item.
Array(1)(3) = H
'Entire row.
Array(1) = {E, F, G, H}
Moving on...
Since BDLL_ReadBlock() seems to expect an array of bytes you should change your C++ method to take one as well (if you have access to the source, that is):
extern "C" BASICDLL_API int __stdcall My_Read_High_Speed_Data(unsigned char ptr, unsigned char *buf)
{
return BDLL_ReadBlock(0x00300000 + ptr, buf);
}
Then change the VB.NET declaration:
<DllImport("MyDll.dll", CallingConvention:=CallingConvention.StdCall)>
Public Function My_Read_High_Speed_Data(ByVal ptr As Byte, ByVal buf As Byte()) As Integer
End Function
Finally, change your VB.NET array to a jagged one, instead of a 2D array:
Dim input_page_buffer(64 - 1)() As Byte
'In VB.NET you specify the upper bound INDEX of an array, not how many items it should contain.
'Thus "Dim Array(64)" creates an array of 65 items (since indexes are zero-based), and "Dim Array(64 - 1)" or "Dim Array(63)" creates an array of 64 items.
The only backside to this is that you must initialize the inner arrays of a jagged array separately:
For x = 0 To input_page_buffer.Length - 1
input_page_buffer(x) = New Byte(256 - 1) {}
Next
And finally, calling the function:
Function poll()
Dim page_index As Byte = 1
'input_page_buffer(0) gives you the first 256-byte array.
Dim success As Integer = My_Read_High_Speed_Data(page_index, input_page_buffer(0))
...
End Function
If you cannot change the source of the C++ code then just replace every Byte(...) in my code with UShort(...) and you should be good to go!

How exactly does a reference to an array work?

I am looking at a unique example here and am trying to understand why his snippet behaves the way it does
// uninitialized mem
char test[99999];
//
test[0] = 'a';
test[1] = 'b';
test[2] = 'c';
test[3] = 'd';
test[4] = 'e';
test[5] = 'f';
test[6] = 'g';
for (int i = 0; i < 99999; i++) {
cout << (&test[i])[i] << endl;
}
In particular, what is happening in memory for the output to skip a character?
output:
a
c
e
g
..
This is what is happening:
An array is just a contiguous chunk of memory.
&test
Is getting the address of that index of the starting point of array. Not the value.
When you add [some number], it counts up the number times the size of the data type, in this case each char is a byte.
So when you do
&test[i]
that means the starting address + i bytes.
when you do
(&test[i])[i]
You are doing i bytes from the starting address, and then treat that as the starting address and go up i more bytes.
So in your iterations:
(&test[0])[0] // index 0 + 0 = 0
(&test[1])[1] // index 1 + 1 = 2
(&test[2])[2] // index 2 + 2 = 4
(&test[3])[3] // index 3 + 3 = 6
It should become a bit more obvious when you consider what the array indexing is actually doing.
Given an array test, you usually access the nth element of test with test[n]. However, this is actually the equivalent of *(test+n). This is because addition on pointers automatically multiplies the amount you add with the size of the type being pointed to. This means the pointer will then be pointing at the second item in the array if you add one to the pointer, the third item if you add two, and so on.
The code you provide then references that value, so you end up with &(*(test+n)). The reference (&) and the dereference (*) operations then cancel each other out, which means you end up with just test+n.
The code then does another array index on that value, so you end up with (test+n)[n], which again may be written as *((test+n)+n). If you simplify that, you get *(test+n+n), which may be rewritten as *(test+2*n).
Clearly then, if you convert that back to array indexing notation, you end up with test[2*n], which indicates in simple form that you'll be querying every other element of the array.

Pointer + Number

I have this code:
How can i debug with printf?
char *string = "something";
short i;
i = strlen(string);
while (i-- && (*(string+i)==' ' || *(string+i)=='\0'));
*(string+i+1) = '\0' ;
What does this do?
*(string+i)
According to the C standard, the expression e1[e2] is by definition equivalent to *(e1+e2). So when you write
*(string + i)
it is equivalent
string[i]
This definition has an interesting side effect that it is actually correct to write 3[s] instead of s[3] as operator [] is commutative.
*(string+i) is string[i]. So *(string+i) == '\0' is the same as string[i] == 0.
This is because pointer + number is the same address as pointer + number * sizeof(type) (in your case string + i is the same a string + i * sizeof(char). When you index into an array arr[i] is the element at address arr + i * sizeof(type).
To debug with printf you simply insert printf statements and poke around the content of variables. For example:
char *string = "something";
short i;
i = strlen(string);
printf("Debug i = %d\n", i);
The postfix operator -- means that i will get evaluated and then decremented before the next sequence point.
The && operator has a sequence point between the left and right operand, so i-- occurs before the right operand is evaluated.
Therefore string+i refers to the value of the original i - 1.
*(string+i) is guaranteed to be completely equivalent with string[i]. The former is just a less readable form.
The code does a peculiar check. If a character is the null terminator, it adds another null terminator behind the first one. That doesn't make any sense. Only the check for space makes some sense.
I also doubt the true intention is to add a null after the space? Wouldn't you rather want to remove the space and end the string there? Seems like a mistake.
Also the code is inefficient, because if you count from the beginning to the end and encounter the first space there, you can stop iterating.
In other words, this code is just awful. You should replace it with something like this:
char* ptr = strchr(string, ' ');
if(ptr != NULL)
{
*ptr = '\0';
}

Pointer Arithmetic? What is the difference between these three expressions?

So I am trying to understand two things:
What are the differences between these three expressions?
What is the equivalent to the first expression (A)?
Here is the code (fixed):
#include "stdafx.h"
void someFunc(double** pArray, int length)
{
for(int i = 0; i < length; i++)
{
//this works perfectly
double expressionA = *(*pArray + i);
//this crashes : Unhandled exception at 0x00da13ff in pptrtest.exe: 0xC0000005: Access violation reading location 0xcccccccc.
double expressionB = **(pArray + i);
//this crashes : Unhandled exception at 0x00da13ff in pptrtest.exe: 0xC0000005: Access violation reading location 0xcccccccc.
double expressionC = *pArray[i];
}
}
int main()
{
double arr[] = { 1, 2, 3, 4, 5 };
double* pArr = arr;
someFunc(&pArr, sizeof arr / sizeof arr[0]);
return 0;
}
I think the problem is, that [] is applied before *, so in expr C you are doing
*(ppDoubleArray[i])
actually the equivalent of expr B, but the expr A does
(*ppDoubleArray)[i]
(assuming the 1 in the expression should be an i, otherwise thats different anyway).
You have a pointer to a pointer of double. Think of it as a pointer to an array of doubles. Either ways, the following is their meanings:
double expressionA = *(*ppDoubleArray + 1); is the same as: double expressionA = *((*ppDoubleArray) + 1);
double expressionB = **(ppDoubleArray + 1); is the same as: double expressionB = *(*(ppDoubleArray + 1)); which means you want to de-reference ppDoubleArray[1] which am guessing doesn't exist.
double expressionC = *ppDoubleArray[i]; is the same as: double expressionC = *(ppDoubleArray[i]); -- again, you are de-referencing ppDoubleArray[i] which does not exist.
Like everyone else said, you need to be mindful of the order of preference. Basically, dereference first then index your array.
double expressionB = **(ppDoubleArray + 1);
Lets look at memory for this guy, on the stack you've got a pointer to a pointer to a double. So if its an address in memory for a 32-bit processor, the stack could look something like:
stack: |ppDoubleArray ptr |local vars, other args, or garbage |more locals/etc
addr: |0 bytes from stack |4 bytes from stack |8bytes...
So when we look at the first part of the expression
(ppDoubleArray + 1)
This says "go one pointer past ppDoubleArray". Go to the next pointer by going to the next spot in memory. What is the next spot in memory past ppDoubleArray? Look at the stack above, its probably some local variables or the other argument. So now you have who knows what (maybe the contents of length? one of the doubles? garbage?) and you're going to treat it as if it were a valid address somewhere. You then follow that supposed pointer, by dereferencing:
**(ppDoubleArray + 1)
And crash!
So, for example, if length was 5, ppDoubleArray+1 might grab 5 and dereference "5" looking for something at that address.
This code:
double expressionC = *ppDoubleArray[i];
works the same way, the [] take precedence over the dereference. So you go to the ith memory location past ppDoubleArray and assume its pointing at your array.
Rearranging the order of operations with parent would, however work:
(*ppDoubleArray)[i]
Assuming ppDoubleArray is a pointer to an array of doubles:
The second one crashes because you are adding one to the pointer to the array not selecting the correct index from it.
The third one crashes because of the precedence of the operators. you are selecting the ith element which is not the array (unless i is 0) and then dereferencing that.
The important thing to remember here is how to deal with a pointer to an array (or a pointer to a pointer) You dereference it once to get to the array, at which point you can do the arithmetic and then dereference it again to get to the element.
aSCII art Time:
---> = derefering
double expressionA = *(*ppDoubleArray + 1);
ppDoubleArray ---> .
+1
. ---> expressionA
double expressionB = **(ppDoubleArray + 1);
ppDoubleArray
+1
. ---> . ---> expressionB
double expressionC = *ppDoubleArray[i];
ppDoubleArray
+i
. ---> . ---> expressionC