- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define NUMARGS(type,...) (sizeof((type[]){__VA_ARGS__})/sizeof(type))
#define xDEF(type) typedef struct {size_t size; type* arr; } xARR(type)
#define xARR(type) jArr_ ## type
#define A(type, ...) (xARR(type)) {NUMARGS(type,__VA_ARGS__), (type[]){__VA_ARGS__}}
#define _FOR(type, item, Arr) type item=Arr.arr[0]; for(size_t I = 0; I < Arr.size; item=Arr.arr[++I] )
// MSVC
#define xFOR(type, item, array) do{ _FOR(type, item, array) {
// GCC, Clang
#define FOR(item, array) do{ __auto_type Arr=array; _FOR(__auto_type, item, Arr) {
#define NEXT }} while(0);
#define OfArray(type,arr) (xARR(type)){sizeof(arr)/sizeof(type), arr }
typedef struct {
char *name;
int id;
} Entry;
typedef struct {const char *name;} Str;
typedef struct {int x[2]; } Pair;
xDEF(Entry);
xDEF(Str);
xDEF(Pair);
xDEF(int);
void printEntry(xARR(Entry) entries)
{
xFOR(Entry, e, entries)
printf("%s %d \n", e.name, e.id);
NEXT
}
void printSquares(xARR(int) ints)
{
FOR(v, ints)
printf("%d²=%d\n", v,(int) pow(v,2.));
NEXT
}
int main(void)
{
xARR(Entry) e = A(Entry, {"one",1}, {"two",2}, {"three",3});
printEntry(e);
puts("_______________________________________");
// можно передавать в метод непосредственно аргуметом
printSquares( A(int, 3, 7, 5, 4) );
puts("_______________________________________");
int nums[]={4,3,2,1};
// можно использовать ранее объявленный массив
printSquares(OfArray(int,nums));
// можно итерироватьcя по ранее объявленному массиву
FOR(i, OfArray(int, nums))
printf("%d-",i);
NEXT
puts("\n_______________________________________");
//вложенные циклы:
for (int k=1;k<3;k++)
FOR(i, A(Str, "kakoi", "bagor"))
FOR(j, A(int, 1111,2222,3333))
printf("%d %s %d\n", k, i.name, j);
NEXT
NEXT
puts("_______________________________________");
FOR(v, A(Pair, {1,2}, {11,12}, {20,21}))
printf("%d,%d\n", v.x[0], v.x[1]);
NEXT
puts("_______________________________________");
//проблема пустого варарга
FOR(j, A(int))
printf("%d\n", j);
NEXT
return(0);
}
Сделал слайсы как в std::span
9/10.
В общем вечер пятницы, ночь субботы. Решил ещё поработать напильником.
Теперь можно мутировать массивspan в цикле.
Бонусом поддерживается любая функция и каст
https://godbolt.org/z/anMYvooxn
В Сишке есть тонкая грань между массивом и указателем, выражается она в том что на одном sizeof работает правильно, а на другом нет. Но я долгое время никак не мог её выразить в ошибку компилятора.
Да, в гцц есть -Wsizeof-pointer-div. Но это ворнинг, который анскильные нубы игнорят, не читают. Потому хотелось именно жёсткую ошибку. Пока не заглянул в ядро.
Магия тут в гццизме (не)совместимости типа массива и указателя на его начало
__builtin_types_compatible_p(typeof(a), typeof(&(a)[0]))
sizeof для указателя совершенно верно работает: он возвращает размер указателя:)
Йеей! Мокросы!
(т.е. есть, но оно не делает то же, что в крестопараше, см. https://stackoverflow.com/questions/2192547/where-is-the-c-auto-keyword-used )
хотя это гну экстеншен, впрочем как и "__auto_type"
А если это не гнусня, тогда придётся использовать xFOR, где нужно явно указать тип.
Так работает и в MSVC (я проверил).
Просто это несколько неэстетично, т.к. его придётся писать джважды для составных макросов.
xFOR(int, i, OfArray(int, nums))
Правильное замечение.
typeof предпочтительнее, поскольку он поддерживается в православном tcc
А __auto_type там нет.
https://bellard.org/tcc/tcc-doc.html#GNU-C-extensions
Я лоханулся, потому что не знаю Сишки.
Declaring vehicles.
но она и так блин локальна по умолчанию
в си не нужно auto, потому что там нет шоблонов
auto завезли не чтобы заменять им char, а чтобы не выписывать значение для ридонли итератора по мапе
the default value semantics of the new range-based for loop, whereas previous
methods of looping over containers resulted in reference semantics. This was
8 A. Parsai et al. noted previously by Stephan Lavavej [14]. In his standard proposal, he lists three problems with the most idiomatic-looking range-based for loop, for (auto elem : range), namely:
– It might not compile - for example, unique ptr3 elements are not copyable.
This is problematic both for users who won’t understand the resulting com-
piler errors, and for users writing generic code that’ll happily compile until
someone instantiates it for movable-only elements.
– It might misbehave at runtime - for example, elem = val; will modify the
copy, but not the original element in the range. Additionally, &elem will be
invalidated after each iteration.
– It might be inefficient - for example, unnecessarily copying std::string.
From a mutation testing perspective, the second reason is the main motivation to create a mutation operator. In the case of a range-based for loop that
modifies the elements of a container in-place, the correct and generic way to
write it is for (auto&& elem : range). For all cases except for proxy objects
and move-only ranges, for (auto& elem : range) works as well
Какие-то &, &&, какие-то конструкторы копирующие, movable.
В крестах всё так сложно и всё так запутанно
Сиплюструп прав, а я виноват.
https://arxiv.org/pdf/2004.04206.pdf
Страуструп — точно наш кандидат!
Борманд именно на нём писал свой AES в Сишном компайлтайме.
https://www.boost.org/doc/libs/1_79_0/libs/preprocessor/doc/index.html
На самом деле сильно упрощает мракоёбство.