In C:
int a[10];
printf("%p\n", a);
printf("%p\n", &a[0]);
Yields:
0x7fff5606c600
0x7fff5606c600
Which is what I expect. Now, in D, I'm trying this (obviously no use case, just fooling around):
int[] slice = [...];
writeln(&slice);
writeln(&slice[0]);
Yields:
7FFF51600360
10E6E9FE0
Why the difference? Looks like a completely different memory segment. (Though it just occurred to me that perhaps arrays in D aren't just adjacently allocated ints?)
in D an array is essentially a struct with a pointer and a length field and is treated as such
to get the address to the first element you can query the ptr field
It is simple - dynamic D arrays are not the same as C arrays. Dynamic D arrays hold the length of the array, while C arrays do not. As such dynamic D arrays do not rely on a NULL to mark the end of the array. As Adam points out in his comment, static D arrays behave the same as C arrays.
import std.stdio;
int main() {
// static array
int[10] sarr;
writeln(sarr.length);
writeln(&sarr);
writeln(&sarr[0]);
// dynamic array
int[] darr = [1, 2, 3];
writeln(darr.length);
writeln(&darr);
writeln(&darr[0]);
// These are all the same
writeln(darr.ptr);
writeln(cast(void*) darr);
writeln(&darr[0]);
return 0;
}
(DPaste link: http://dpaste.dzfl.pl/f708d945)
Because "array" used by itself resolves to a pointer to the array, this allows you to treat pointer-to-type and array-of-type somewhat similarly when using structs.
int[] slice = [...];
writeln((cast(void*) slice);
writeln(&slice[0]);
should give you what you want.
Inherited from "C" http://c-faq.com/aryptr/aryptrequiv.html
int[] slice = [...];
int* ptr = &slice[0];
writeln(cast(void*) slice);
writeln(&slice[0]);
// value access
writeln(slice[0]);
writeln(*ptr);
writeln(ptr[0]);
Related
I need to initialize array of
array[921600] = {229407, 229407, 229407,...,226851};
elements, I allocated array for 921600 elements and initialized array in function:
setArray(array);
and function looks like this:
Void setArray(Uint8 *array){
array[921600] = {229407, 229407, 229407,...,226851}; //shorten
}
and then I get error in compiler: error: expected an expression.
When I initialize elements one by one it works like this:
Void setArray(Uint8 *array)
{
*(array + 0) = (3);
*(array + 1) = (2);
*(array + 2) = (2);
}
In C, you can initialize an array as you declare it [^1]
For example:
int digits[] = { 3, 1, 4, 1, 5, 9, 2, 6 }; // Initialize an array of 8 numbers
However, after an array is created, you cannot use the same syntax to assign it. Initialization and Assignment are two different operations with different rules.
The closest thing to a bulk assignment I know of is an ugly memcpy using a compound-literal.
memcpy(digits, (int[]){3,1,4,1,5,9,2,6}, sizeof(digits));
Example Code:
#include <stdio.h>
#include <string.h>
int main(void) {
int digits[8];
memcpy(digits, (int[]){3,1,4,1,5,9,2,6}, sizeof(digits));
for(int i=0; i<8; ++i)
{
printf("%d", digits[i]);
}
return 0;
}
But that technique would be extremely difficult (and wasteful) to do on an array of 921600 elements. For a very big array, the data should likely be loaded from a compiled resource or a text file or a similar external source.
[^1]: Except for VLAs. VLAs cannot be initialized this way.
First of all, this:
array[921600] = {229407, 229407, 229407,...,226851} //shorten
doesn't assign the entire array - it's attempting to assign a brace-enclosed list to a single array element (which is a syntax error), and that element is one past the end of the array (if there are 921600 elements in the array, then they are indexed from 0 to 921599).
You cannot assign an entire array's contents using the = operator - if you want to set all elements to the same value you can use memset, otherwise you'll have to assign elements individually.
Your compiler should also be yakking on Void and Uint8 - are you sure you don't mean void (C is case-sensitive) and uint8_t? And if you mean for the elements to be 8 bits unsigned, then they won't be able to represent values like 229407 or 226851.
This doesn't work:
array[921600] = {229407, 229407, 229407,...,226851};
Because you're actually attempting to assign (not initialize) a single value in array, and the {...} syntax is only valid for an initialization.
If you have some fixed set of values you're going to use to set your array, you can place them in another array and copy them in:
void setArray(uint8 *array)
{
static const int src[921600] = {229407, 229407, 229407,...,226851};
memcpy(array, src, sizeof src);
}
By making the source array static, you avoid having a large temporary array that could potentially blow up the stack.
How to copy row of 2d array to 1d array?
I was sure before I done it by assign like that:
int x,y;
scanf("%d%d", &x,&y);
int one[x];
int two[y][x];
one=two[0];
But now it gives me error :
incompatible types in assignment
EDIT:
Ok, my bad.
I forgot that I can't copy arrays in such way, but I can pass single row of 2d array to function as an argument. Solved.
You are trying to assign from a 2-dimensional array into 1-dimensional array! You will have to loop through the 2-d array and select each individual value and insert into 1-d array.
You can't do
one=two[0]; // Illegal assignment in C
Array names are non-modifiable l-values. It can't be a left operand of assignment operator =. You can do this as
one[x] = two[y][x];
Just use this code :
int col,rowToCopy=0;
for(col=0;col<x;col++){
one[col]=two[rowToCopy][col];
}
It seems that it isn't accepted ( I am not completely sure - I will look better ).
The semantics of the language are that for a unidimensional array the name of the array is a pointer to the type of element of the array and exactly a pointer to the first element.
In your case the array is just a pointer of type (int*).
On any (int*) we may apply the [] brackets.
These brackets as I have checked just translate to add the number inside the square brackets to the pointer ( using the pointer arithmetics ) and applying a dereference to the pointer.
Explained in other words:
int *p;
p[nn] is equivalent to *(p+nn);
So in that vision having the code bellow:
int a[8],b[8];
a=b;
doing a=b could only copy the content of pointer b to the pointer a.
But because the array is a constant pointer with no possibility to change that isn't possible.
So the code above would report an error;
Any way if it was possible it would copy the address where the array b starts to the pointer a.
And that any way isn't what you need or what you expect.
That is the way that C treats arrays ( thanks for having obliged me to think on it ).
In the case the size was fixed I would do like that:
typedef struct{int arr[0x4];}S;
S a,b;
a=b;
In order to access the array you should use: a.arr[] and b.arr[]
In case you need an array of arrays it would be simple to extend to your case.
The problem is that in your case the size is dynamic.
The only simple solution is to use:
memcpy(a,b,sizeof(a));
That has the effect of copying b into a as you need. Every other solution is more complicated.
The below code may solve your problem:
#include<iostream>
#include<string.h>
using namespace std;
int main()
{
int i,row,col,col1;
char value1[10][4]={};
char *value2;
value2 = new char[40];
/** Creating a 2D char array ***/
for(i=0;i<8;i++)
{
strcpy(value1[i],"MK,");
}
value1[7][strlen(value1[7])-1]='\0';
/*** Printing the 2D array ****/
for(i=0;i<8;i++)
{
cout<<"\n\n value1[i]="<<value1[i];
}
/*** assigning the 2D array value1[][] to string value2 **/
col1=0;
for(row=0;value1[row][0]!='\0';row++)
{
for(col=0;value1[row][col]!='\0';col++)
{
*(value2+col1) = value1[row][col];
col1++;
}
}
*(value2+col1)='\0';
/** assignment done ***/
cout<<"\n\nSize of rows="<<row<<"\n\nSize of Column="<<col;
cout<<"\n\nvalue1="<<value1[0];
cout<<"\n\nValue2="<<value2;
return 0;
}
I'm trying to make a deep copy of an array in C (originalBoard being the copy):
int gy, gx;
for (gy=0; gy<9; gy++)
{
for (gx=0; gx<9; gx++)
{
g.originalBoard[gy][gx]=g.board[gy][gx];
}
}
This does not seem to be working out, and I'm guessing this is just making pointers to the original board array.
So would the solution be to try and use malloc? Like:
int* g.originalBoard[9][9]=malloc(sizeof(g.board[9][9]));
btw this is a 9x9 two dimensional array. What would the syntax be (the compiler gives an error for the above line...)?
I think you need this:
//assuming g.originalBoard is array of array of integers and same for g.board
int *originalBoard = malloc(sizeof(g.board));
memcpy(originalBoard, g.board, sizeof(g.board));
This is the correct place to use memcpy. You probably want
g.originalBoard = (int *)malloc(9 * 9 * sizeof(int));
if (NULL == g.originalBoard) {
/* malloc failed, so handle the error somehow */
}
memcpy(g.originalBoard, g.board, 9 * 9 * sizeof(int));
You may notice that in the above solution you have to use g.board[r * 9 + c] to access the item at index (r, c), rather than two indices. This is because of the way this dynamically allocates memory - at compile-time g.board and g.originalBoard are just pointers, not arrays. Alternatively, if you have control over the definition of the type of g, you can hardcode the size of the matrix as
struct foo {
int board[9][9];
int originalBoard[9][9];
/* Other fields here */
};
Then you wouldn't have to malloc extra space for g.board and g.originalBoard - those two fields would be automatically allocated whenever you allocated space for g itself. Also, you could use g.board[r][c] instead of g.board[r * 9 + c].
By the way, if you are trying to execute the following 'intended' task on the arrays,
int* g.originalBoard[9][9]=malloc(sizeof(g.board[9][9]));
then you should change the above line to
int* g.originalBoard[8][8]=malloc(sizeof(g.board[8][8]));
because this is a 9x9 two dimensional array and in C arrays are ZERO-based.
Sorry, this became a 3-fold question regarding arrays
I think (dynamic) arrays are truly powerful in D, but the following has been bothering me for a while:
In C++ I could easily allocate an array with designated values, but in D I haven't found a way to do so. Surely the following is no problem:
int[] a = new int[N];
a[] = a0;
But it looks inefficient, since line one will initialize with 0, and like 2 with a0. Could something similar to the following be done in D?
int[] a = new int(a0)[N]; // illegal
Another efficiency matter I have when using stride in std.range:
import std.stdio;
import std.range;
struct S
{
int x;
this(this)
{
writeln("copy ", x);
}
}
void f(S[] s)
{
}
int main()
{
S[] s = new S[10];
foreach (i, ref v; s)
{
v.x = i;
}
f(stride(s, 3)); // error
return 0;
}
Surely I was naive thinking I could simply use stride to create a new array without copying it's elements? There is no way to do so in D, right?
So I went and simulated as if the array was as stride would return, and implemented f as:
f(s, 3);
void f(S[] s, uint stride)
{
ref S get(uint i)
{
assert (i * stride < s.length);
return s[i * stride];
}
for (uint x ... )
{
get(x) = ...;
}
}
Would there be a way to instead write get(x) using the index operator get[x]? This way I could statically mixin / include the striding get function and keep the rest of the function similar. I'd be interested in the approach taken, since a local struct is not allowed to access function scope variables (why not?).
But it looks inefficient, since line one will initialize with 0, and like 2 with a0. Could something similar to the following be done in D?
Use std.array.uninitializedArray
S[] s = uninitializedArray!(S[])(N);
s[] = a0;
Surely I was naive thinking I could simply use stride to create a new array without copying it's elements? There is no way to do so in D, right?
Your function f has an S[] as an argument, which is different from what stride returns. The D way to solve this is to make your f function accept any range by making it a template:
void f(Range)(Range s)
{
foreach (item; s)
// use item
}
S[] s = new S[10];
f(s); // works
f(stride(s, 3)); // works too
Alternatively you can copy the array:
f(array(stride(s, 3)));
But you probably want to avoid copying the entire array if it is large.
Would there be a way to instead write get(x) using the index operator get[x]? This way I could statically mixin / include the striding get function and keep the rest of the function similar. I'd be interested in the approach taken, since a local struct is not allowed to access function scope variables (why not?).
You can overload the indexing operator in your own struct.
struct StrideArray
{
this(S[] s, uint stride) { m_array = s; m_stride = stride; }
S opIndex(size_t i) { return s[i * m_stride]; }
void opIndexAssign(size_t i, S value) { s[i * m_stride] = value; }
private S[] m_array;
private uint m_stride;
}
This is (kind of) the way the actual stride function works. I'd recommend reading up on Ranges.
you can duplicate (create a copy of) an array with .dup (this will also work with slices) or you can set the elements with the array initializer
int[] a=a0.dup;
int[] b=[e1,e2,e3];
you can make the f generic (stride() returns a struct that you can iterate over, not an array)
void f(Z)(Z s)if(isInputRange!Z){
foreach(elem;s){
//...
}
}
remember that arrays are essentially structs with a pointer field to some memory block and a size field
What are the differences between an array of char pointers and a 2D array?
char* pasz[3] = {"abc", "def", "ghi"};
char asz[3][] = {"abc", "def", "ghi"};
The similarities and differences are basically the same as between these two:
char *psz = "jkl";
char sz[] = "jkl";
The first is originally read-only.
psz[0] = 'a'; // Illegal!!
The second, you can modify, since you allocate it with the [].
sz[0] = 'b';
// sz == "bkl"
The first, you can modify what it points to:
char mysz[] = "abc";
psz = mysz;
psz[0] = 'b';
// mysz == "bbc"
The second, you cannot:
sz = mysz; // Can't assign an array to an array!!
char* my_string[];
represents an array of strings.
int my_grid_of_ints[][];
char my_block_of_text[][];
If color = byte[3] then you could represent your screen monitor
color my_pixel_buffer[][] = new color[768][1024];
is a 2D array. As you can see, a 2D array can represent anything, including an array of char pointers (such as multiple lines of strings).
You can access elements with the same syntax, but the guarantees about memory layout is much different. The 2d array is contiguous. The array of pointers is not.
Array of arrays (aka multi-dimensional array) looks like (in memory):
a[0][0], a[0][1], a[0][n-1], a[1][0], a[1][1], ..., a[1][n-1], ..., a[m-1][n-1]
array of pointers looks like:
p[0], p[1], ..., p[m-1]
where each slot is a pointer and can point to whatever. If they all happen to point to arrays with n elements each, then p[i][j] and a[i][j] can be used similarly in expressions, but they're actually quite different objects.