回答編集履歴
3
バグの修正とassertの追加
test
CHANGED
@@ -194,6 +194,8 @@
|
|
194
194
|
|
195
195
|
```C
|
196
196
|
|
197
|
+
#include <assert.h>
|
198
|
+
|
197
199
|
#include <stdio.h>
|
198
200
|
|
199
201
|
#include <stdlib.h>
|
@@ -224,7 +226,7 @@
|
|
224
226
|
|
225
227
|
int size;
|
226
228
|
|
227
|
-
i
|
229
|
+
size_t mem_size;
|
228
230
|
|
229
231
|
void *mem;
|
230
232
|
|
@@ -236,13 +238,17 @@
|
|
236
238
|
|
237
239
|
{
|
238
240
|
|
241
|
+
assert(0 <= size);
|
242
|
+
|
239
243
|
struct data_all dd;
|
240
244
|
|
241
245
|
dd.size = size;
|
242
246
|
|
243
247
|
dd.mem_size = sizeof(struct head) + sizeof(struct data) * size +
|
244
248
|
|
245
|
-
|
249
|
+
sizeof(int) * 3 * 4 * size;
|
250
|
+
|
251
|
+
assert(0 <= dd.mem_size);
|
246
252
|
|
247
253
|
dd.mem = calloc(1, dd.mem_size);
|
248
254
|
|
@@ -266,6 +272,8 @@
|
|
266
272
|
|
267
273
|
{
|
268
274
|
|
275
|
+
assert(dd.mem != NULL);
|
276
|
+
|
269
277
|
return (struct head *)dd.mem;
|
270
278
|
|
271
279
|
}
|
@@ -274,9 +282,13 @@
|
|
274
282
|
|
275
283
|
{
|
276
284
|
|
285
|
+
assert(dd.mem != NULL);
|
286
|
+
|
287
|
+
assert(0 <= n && n < dd.size);
|
288
|
+
|
277
289
|
return (struct data *)(dd.mem + sizeof(struct head) +
|
278
290
|
|
279
|
-
|
291
|
+
sizeof(struct data) * n);
|
280
292
|
|
281
293
|
}
|
282
294
|
|
@@ -286,9 +298,21 @@
|
|
286
298
|
|
287
299
|
{
|
288
300
|
|
301
|
+
assert(dd.mem != NULL);
|
302
|
+
|
303
|
+
assert(0 <= n && n < dd.size);
|
304
|
+
|
305
|
+
assert(0 <= x && x < 4);
|
306
|
+
|
307
|
+
assert(0 <= y && y < 3);
|
308
|
+
|
289
|
-
|
309
|
+
size_t forward = sizeof(struct head) + sizeof(struct data) * dd.size +
|
290
|
-
|
310
|
+
|
291
|
-
|
311
|
+
sizeof(int) * (n + dd.size * x + dd.size * 4 * y);
|
312
|
+
|
313
|
+
assert(forward < dd.mem_size);
|
314
|
+
|
315
|
+
return (int *)(dd.mem + forward);
|
292
316
|
|
293
317
|
}
|
294
318
|
|
@@ -322,6 +346,14 @@
|
|
322
346
|
|
323
347
|
dd = data_all_create(rec_size);
|
324
348
|
|
349
|
+
if (dd.mem == NULL) {
|
350
|
+
|
351
|
+
fprintf(stderr, "Failed to allocate memory.\n");
|
352
|
+
|
353
|
+
return 1;
|
354
|
+
|
355
|
+
}
|
356
|
+
|
325
357
|
// 既にあるデータ構造を入れる場合は、次のようにする。
|
326
358
|
|
327
359
|
// memcpy(dd.mem, ○○, dd.mem_size);
|
@@ -348,9 +380,9 @@
|
|
348
380
|
|
349
381
|
// data[y][x][n] = ...
|
350
382
|
|
351
|
-
data_all_set_value(
|
383
|
+
data_all_set_value(
|
352
|
-
|
384
|
+
|
353
|
-
n * (y + 1) - x);
|
385
|
+
dd, n, x, y, n * (y + 1) - x);
|
354
386
|
|
355
387
|
}
|
356
388
|
|
@@ -360,17 +392,17 @@
|
|
360
392
|
|
361
393
|
printf("%d: %s\n", data_all_data(dd, 3)->no,
|
362
394
|
|
363
|
-
|
395
|
+
data_all_data(dd, 3)->name);
|
364
396
|
|
365
397
|
printf("%d: %s\n", data_all_data(dd, 99999)->no,
|
366
398
|
|
367
|
-
|
399
|
+
data_all_data(dd, 99999)->name);
|
368
|
-
|
400
|
+
|
369
|
-
printf("%d\n", data_all_get_value(dd, 0, 0, 0));
|
401
|
+
printf("%d\n", data_all_get_value(dd, 0, 0, 0)); // 最小値
|
370
402
|
|
371
403
|
printf("%d\n", data_all_get_value(dd, 42, 1, 1));
|
372
404
|
|
373
|
-
printf("%d\n", data_all_get_value(dd, 99999,
|
405
|
+
printf("%d\n", data_all_get_value(dd, 99999, 3, 2)); // 最大値
|
374
406
|
|
375
407
|
data_all_destroy(dd);
|
376
408
|
|
2
2\.の条件が抜けていた。
test
CHANGED
@@ -177,3 +177,209 @@
|
|
177
177
|
Q: これってCの標準仕様?
|
178
178
|
|
179
179
|
A: だと思ったけど、調べ切れてないです。わかる人は教えてください。
|
180
|
+
|
181
|
+
|
182
|
+
|
183
|
+
---
|
184
|
+
|
185
|
+
|
186
|
+
|
187
|
+
> 2.入れ子の構造体の領域は、使用している独自処理のため、連続したメモリ領域である必要がある。
|
188
|
+
|
189
|
+
|
190
|
+
|
191
|
+
という制限があったのですね。struct data_allの構造を変えずにするとなると、普通に構造体や配列としてアクセスする方法では無理です。メモリを自分で確保して、直接計算してアクセスするしかないと思います。ということで、書き直しました。
|
192
|
+
|
193
|
+
|
194
|
+
|
195
|
+
```C
|
196
|
+
|
197
|
+
#include <stdio.h>
|
198
|
+
|
199
|
+
#include <stdlib.h>
|
200
|
+
|
201
|
+
|
202
|
+
|
203
|
+
struct head {
|
204
|
+
|
205
|
+
int size;
|
206
|
+
|
207
|
+
char ver[10];
|
208
|
+
|
209
|
+
};
|
210
|
+
|
211
|
+
|
212
|
+
|
213
|
+
struct data {
|
214
|
+
|
215
|
+
int no;
|
216
|
+
|
217
|
+
char name[30];
|
218
|
+
|
219
|
+
};
|
220
|
+
|
221
|
+
|
222
|
+
|
223
|
+
struct data_all {
|
224
|
+
|
225
|
+
int size;
|
226
|
+
|
227
|
+
int mem_size;
|
228
|
+
|
229
|
+
void *mem;
|
230
|
+
|
231
|
+
};
|
232
|
+
|
233
|
+
|
234
|
+
|
235
|
+
struct data_all data_all_create(int size)
|
236
|
+
|
237
|
+
{
|
238
|
+
|
239
|
+
struct data_all dd;
|
240
|
+
|
241
|
+
dd.size = size;
|
242
|
+
|
243
|
+
dd.mem_size = sizeof(struct head) + sizeof(struct data) * size +
|
244
|
+
|
245
|
+
sizeof(int) * 3 * 4 * size;
|
246
|
+
|
247
|
+
dd.mem = calloc(1, dd.mem_size);
|
248
|
+
|
249
|
+
return dd;
|
250
|
+
|
251
|
+
}
|
252
|
+
|
253
|
+
void data_all_destroy(struct data_all dd)
|
254
|
+
|
255
|
+
{
|
256
|
+
|
257
|
+
free(dd.mem);
|
258
|
+
|
259
|
+
dd.mem = NULL;
|
260
|
+
|
261
|
+
}
|
262
|
+
|
263
|
+
|
264
|
+
|
265
|
+
struct head *data_all_head(struct data_all dd)
|
266
|
+
|
267
|
+
{
|
268
|
+
|
269
|
+
return (struct head *)dd.mem;
|
270
|
+
|
271
|
+
}
|
272
|
+
|
273
|
+
struct data *data_all_data(struct data_all dd, int n)
|
274
|
+
|
275
|
+
{
|
276
|
+
|
277
|
+
return (struct data *)(dd.mem + sizeof(struct head) +
|
278
|
+
|
279
|
+
sizeof(struct data) * n);
|
280
|
+
|
281
|
+
}
|
282
|
+
|
283
|
+
// data[y][x][n]のこと
|
284
|
+
|
285
|
+
int *data_all_value(struct data_all dd, int n, int x, int y)
|
286
|
+
|
287
|
+
{
|
288
|
+
|
289
|
+
return (int *)(dd.mem + sizeof(struct data) * dd.size +
|
290
|
+
|
291
|
+
sizeof(int) * (n + dd.size * x + dd.size * 4 * y));
|
292
|
+
|
293
|
+
}
|
294
|
+
|
295
|
+
int data_all_get_value(struct data_all dd, int n, int x, int y)
|
296
|
+
|
297
|
+
{
|
298
|
+
|
299
|
+
return *data_all_value(dd, n, x, y);
|
300
|
+
|
301
|
+
}
|
302
|
+
|
303
|
+
void data_all_set_value(struct data_all dd, int n, int x, int y, int value)
|
304
|
+
|
305
|
+
{
|
306
|
+
|
307
|
+
*data_all_value(dd, n, x, y) = value;
|
308
|
+
|
309
|
+
}
|
310
|
+
|
311
|
+
|
312
|
+
|
313
|
+
struct data_all dd; // 可変部分があるため静的に作ることはできない
|
314
|
+
|
315
|
+
|
316
|
+
|
317
|
+
int main(int argc, char *argv[])
|
318
|
+
|
319
|
+
{
|
320
|
+
|
321
|
+
int rec_size = 100000;
|
322
|
+
|
323
|
+
dd = data_all_create(rec_size);
|
324
|
+
|
325
|
+
// 既にあるデータ構造を入れる場合は、次のようにする。
|
326
|
+
|
327
|
+
// memcpy(dd.mem, ○○, dd.mem_size);
|
328
|
+
|
329
|
+
|
330
|
+
|
331
|
+
// ダミーで値を入れてみる
|
332
|
+
|
333
|
+
for (int n = 0; n < dd.size; n++) {
|
334
|
+
|
335
|
+
struct data *d = data_all_data(dd, n);
|
336
|
+
|
337
|
+
d->no = n;
|
338
|
+
|
339
|
+
sprintf(d->name, "%08d", n);
|
340
|
+
|
341
|
+
}
|
342
|
+
|
343
|
+
for (int n = 0; n < dd.size; n++) {
|
344
|
+
|
345
|
+
for (int x = 0; x < 4; x++) {
|
346
|
+
|
347
|
+
for (int y = 0; y < 3; y++) {
|
348
|
+
|
349
|
+
// data[y][x][n] = ...
|
350
|
+
|
351
|
+
data_all_set_value(dd, n, x, y,
|
352
|
+
|
353
|
+
n * (y + 1) - x);
|
354
|
+
|
355
|
+
}
|
356
|
+
|
357
|
+
}
|
358
|
+
|
359
|
+
}
|
360
|
+
|
361
|
+
printf("%d: %s\n", data_all_data(dd, 3)->no,
|
362
|
+
|
363
|
+
data_all_data(dd, 3)->name);
|
364
|
+
|
365
|
+
printf("%d: %s\n", data_all_data(dd, 99999)->no,
|
366
|
+
|
367
|
+
data_all_data(dd, 99999)->name);
|
368
|
+
|
369
|
+
printf("%d\n", data_all_get_value(dd, 0, 0, 0));
|
370
|
+
|
371
|
+
printf("%d\n", data_all_get_value(dd, 42, 1, 1));
|
372
|
+
|
373
|
+
printf("%d\n", data_all_get_value(dd, 99999, 2, 3));
|
374
|
+
|
375
|
+
data_all_destroy(dd);
|
376
|
+
|
377
|
+
return 0;
|
378
|
+
|
379
|
+
}
|
380
|
+
|
381
|
+
```
|
382
|
+
|
383
|
+
C++でクラス作っているような感じで実装すればできるかなと思います。
|
384
|
+
|
385
|
+
|
1
Clangで試したことと、Q&AにVLAISを追加
test
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
|
4
4
|
|
5
|
-
下記の機能を使っており、GCCでしか試していません。
|
5
|
+
下記の機能を使っており、gcc(GCC 5.3.0)とclang(LLVM 7.3.0)でしか試していません。
|
6
6
|
|
7
7
|
[Zero Length - Using the GNU Compiler Collection (GCC)](https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html)
|
8
8
|
|
@@ -156,7 +156,7 @@
|
|
156
156
|
|
157
157
|
Q: `[]`でいいの?
|
158
158
|
|
159
|
-
A: GCCとVCでは0サイズと見なして大丈夫のようです。ただ、それ一つだけだと構造体全体が0サイズになるため、他に何か必要になります。
|
159
|
+
A: GCCとVCでは0サイズと見なして大丈夫のようです。ただ、それ一つだけだと構造体全体が0サイズになるため、他に何か必要になります。`[1]`とする書き方もあるようですが、正式なドキュメントが見つけられませんでした。
|
160
160
|
|
161
161
|
Q: `int value[3][4][]`とはできないの?
|
162
162
|
|
@@ -170,6 +170,10 @@
|
|
170
170
|
|
171
171
|
A: 違います。全く別の機能です。
|
172
172
|
|
173
|
+
Q: 構造体可変長配列(VLAIS)ってこれのこと?
|
174
|
+
|
175
|
+
A: 違います。これまた別の機能です。
|
176
|
+
|
173
177
|
Q: これってCの標準仕様?
|
174
178
|
|
175
179
|
A: だと思ったけど、調べ切れてないです。わかる人は教えてください。
|