-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDiary9.txt
1055 lines (935 loc) · 20.8 KB
/
Diary9.txt
1
2
3
4
5
6
7
8
9
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
【2020-01-27】C++ const 与 auto 结合使用
auto 为 const 结合使用时候
无论是 auto const 或者 const auto
编译都会理解成auto const
若auto为指针 表达意义都是 指针指向不能改变 而指针的数据是允许改变的
若auto为引用 表达意义都是 引用数据不允许改变
例1:
int* acquire_pointer()
{
return new int;
}
void release_pointer(const int* p)
{
delete p;
}
int* const p = acquire_pointer();
// const 在 * 右边
// 指针指向数据值允许改变
*p = 1;
release_pointer(p);
// const 在 * 右边
// 指针指向不能改变
// p = nullptr;
const int* p2 = acquire_pointer();
// const 在 * 左边
// 指针指向数据值不允许改变
// *p2 = 1;
release_pointer(p2);
// const 在 * 左边
// 指针指向能改变
p2 = nullptr;
auto p3 = acquire_pointer();
// auto 为 int*
*p3 = 1;
release_pointer(p3);
// auto 为 int*
p3 = nullptr;
/*
auto 为 const 结合使用时候
如果auto表示的是指针类型 auto const 与 const auto
均表示指针为常量 因此表达意义都是指针指向不能改变
而指针的数据是允许改变的
*/
const auto p4 = acquire_pointer();
// auto 为 int*
// p4 完整类型为 int* const
// const 在 * 右边
// 指针指向数据值允许改变
*p4 = 1;
release_pointer(p4);
// auto 为 int*
// p4 完整类型为 int* const
// 指针指向不能改变
// p4 = nullptr;
auto const p5 = acquire_pointer();
// p5 类型跟 p4 完全一样
// 指针指向数据值允许改变
*p5 = 1;
release_pointer(p5);
// p5 类型跟 p4 完全一样
// 指针指向不能改变
// p5 = nullptr;
例2:
/*
auto 为 const 结合使用时候
如果auto表示的是引用类型 auto const 与 const auto
均表示引用为常量 因此表达意义都是引用数据不允许改变
*/
int num = 0;
{
// n0 与 n1 表达相同意义
// 类型 const int& 与 int const& 没有区别
int const& n0 = num;
const int& n1 = num;
// ++n0;
// ++n1;
}
{
// n0 类型为 int&
auto& n0 = num;
++n0;
auto const& n1 = num;
// n1被const修饰 值不允许改变
// n1完整类型为 int const& (与 const int& 无区别)
// ++n1;
const auto& n2 = num;
// n2被const修饰 值不允许改变
// n2完整类型为 const int& (与 int const& 无区别)
// ++n2;
}
【2020-2-12】C++ std::forward
// https://www.jianshu.com/p/b90d1091a4ff
// https://blog.csdn.net/coolwriter/article/details/80970718
当我们将一个右值引用传入函数时 他在实参中有了命名 所以继续往下传或者调用其他函数时
根据C++标准的定义 这个参数变成了一个左值 那么他永远不会调用接下来函数的右值版本
这可能在一些情况下造成拷贝 为了解决这个问题 C++11引入了完美转发
根据右值判断的推倒 调用forward传出的值
若原来是一个右值 那么他转出来就是一个右值 否则为一个左值
例:
#include <cstdio>
#include <algorithm>
template<typename T2>
void TemplateRefFunc(T2&& t)
{
printf("rvalue reference\n");
t = (T2)1;
}
template<typename T2>
void TemplateRefFunc(T2& t)
{
printf("lvalue reference\n");
t = (T2)0;
}
template<typename T>
void UniversalTemplateForwardFunc(T&& t)
{
TemplateRefFunc(std::forward<T>(t));
}
template<typename T>
void UniversalTemplateFunc(T&& t)
{
TemplateRefFunc(t);
}
int main()
{
printf("test case 1:\n");
{
int val = 0;
int &&val2 = std::move(val);
int &val3 = val;
printf("val a value\n");
printf("val2 is a rvalue reference\n");
printf("val3 is a lvalue reference\n");
printf("call TemplateRefFunc(std::forward<decltype(val)>(val)): ");
TemplateRefFunc(std::forward<decltype(val)>(val));
printf("call TemplateRefFunc(std::forward<decltype(val2)>(val2)): ");
TemplateRefFunc(std::forward<decltype(val2)>(val2));
printf("call TemplateRefFunc(std::forward<decltype(val3)>(val3)): ");
TemplateRefFunc(std::forward<decltype(val3)>(val3));
}
printf("test case 2:\n");
{
int val = 0;
int &&val2 = std::move(val);
printf("val a value\n");
printf("val2 is a rvalue reference\n");
printf("call UniversalTemplateForwardFunc(val): ");
UniversalTemplateForwardFunc(val);
printf("call UniversalTemplateForwardFunc(val2): ");
UniversalTemplateForwardFunc(val2);
printf("call UniversalTemplateForwardFunc(std::move(val2)): ");
UniversalTemplateForwardFunc(std::move(val2));
}
printf("test case 3:\n");
{
int val = 0;
int &&val2 = std::move(val);
printf("val is a value\n");
printf("val2 is a rvalue reference\n");
printf("call UniversalTemplateFunc(val): ");
UniversalTemplateFunc(val);
printf("call UniversalTemplateFunc(val2): ");
UniversalTemplateFunc(val2);
printf("call UniversalTemplateFunc(std::move(val2)): ");
UniversalTemplateFunc(std::move(val2));
}
return 0;
}
输出:
test case 1:
val a value
val2 is a rvalue reference
val3 is a lvalue reference
call TemplateRefFunc(std::forward<decltype(val)>(val)): rvalue reference
call TemplateRefFunc(std::forward<decltype(val2)>(val2)): rvalue reference
call TemplateRefFunc(std::forward<decltype(val3)>(val3)): lvalue reference
test case 2:
val a value
val2 is a rvalue reference
call UniversalTemplateForwardFunc(val): lvalue reference
call UniversalTemplateForwardFunc(val2): lvalue reference
call UniversalTemplateForwardFunc(std::move(val2)): rvalue reference
test case 3:
val is a value
val2 is a rvalue reference
call UniversalTemplateFunc(val): lvalue reference
call UniversalTemplateFunc(val2): lvalue reference
call UniversalTemplateFunc(std::move(val2)): lvalue reference
【2020-2-13】C++ 复制构造 移动构造
1.类定义复制构造函数后 默认的移动构造函数会被删除
template<typename T>
T Call()
{
T a;
return a;
}
class Test
{
protected:
public:
Test()
{
printf("test default ctor\n");
}
Test(const Test& rhs)
{
printf("test lvalue ctor\n");
}
};
int main()
{
Call<Test>();
}
运行期输出:
test default ctor
test lvalue ctor
(调用到复制构造函数 因此没有调用到移动构造函数)
2.类定义移动构造函数后 默认的复制构造函数会被删除
例:
template<typename T>
T Call()
{
T a;
T b(a);
return a;
}
class Test
{
protected:
public:
Test()
{
printf("test default ctor\n");
}
Test(Test&& rhs)
{
printf("test rvalue ctor\n");
}
};
int main()
{
Call<Test>();
}
编译器输出:
C2280 “Test::Test(const Test &)”: 尝试引用已删除的函数
3.对象按值返回 会优先匹配移动构造函数
例:
template<typename T>
T Call()
{
T a;
return a;
}
class Test
{
protected:
public:
Test()
{
printf("test default ctor\n");
}
Test(const Test& rhs)
{
printf("test lvalue ctor\n");
}
Test(Test&& rhs)
{
printf("test rvalue ctor\n");
}
};
int main()
{
Call<Test>();
}
运行期输出:
test default ctor
test rvalue ctor
4.默认的移动构造函数和复制构造函数会对对象的成员调用其对应的移动构造或者复制构造
例1:
class Small
{
protected:
public:
Small()
{
printf("small default ctor\n");
}
Small(const Small& rhs)
{
printf("small lvalue ctor\n");
}
Small(Small&& rhs)
{
printf("small rvalue ctor\n");
}
};
class Big
{
protected:
Small small;
public:
Big()
{
printf("big default ctor\n");
}
};
template<typename T>
T Call()
{
T a;
return a;
}
int main()
{
Call<Big>();
}
运行期输出:
small default ctor
big default ctor
small rvalue ctor
(调用到Big的默认移动构造 其实现则对对象成员同样执行移动构造)
例2:
class Small
{
protected:
public:
Small()
{
printf("small default ctor\n");
}
Small(const Small& rhs)
{
printf("small lvalue ctor\n");
}
Small(Small&& rhs)
{
printf("small rvalue ctor\n");
}
};
class Big
{
protected:
Small small;
public:
Big()
{
printf("big default ctor\n");
}
Big(const Big& rhs) = default;
};
template<typename T>
T Call()
{
T a;
return a;
}
int main()
{
Call<Big>();
}
运行期输出:
small default ctor
big default ctor
small rvalue ctor
(调用到Big的默认复制构造 其实现则对对象成员同样执行复制构造)
【2020-2-15】【1】C++ Lambda 按值捕获静态变量实际上只是按照引用捕获
C++ Lambda 按值捕获静态变量实际上只是按照引用捕获
并没有生成值的拷贝
例:
#include <cstdio>
#pragma warning(disable: 4477)
int main()
{
int localVal = 0;
static int staticVal = 0;
printf("localVal address outside lambda: 0x%08x\n", &localVal);
printf("staticVal address outside lambda: 0x%08x\n", &staticVal);
auto copy = [=]()
{
printf("copy caputure\n");
printf("localVal address inside lambda: 0x%08x\n", &localVal);
printf("staticVal address inside lambda: 0x%08x\n", &staticVal);
};
copy();
auto ref = [&]()
{
printf("reference caputure\n");
printf("localVal address inside lambda: 0x%08x\n", &localVal);
printf("staticVal address inside lambda: 0x%08x\n", &staticVal);
};
ref();
}
输出:
localVal address outside lambda: 0x0034f738
staticVal address outside lambda: 0x01061404
copy caputure
localVal address inside lambda: 0x0034f72c
staticVal address inside lambda: 0x01061404
reference caputure
localVal address inside lambda: 0x0034f738
staticVal address inside lambda: 0x01061404
【2020-2-15】【2】C++定义析构函数将会压制移动(move)成员函数的自动生成
C++定义析构函数将会压制移动(move)成员函数的自动生成
例:
1.
class Small
{
protected:
public:
Small()
{
printf("small default ctor\n");
}
Small(const Small& rhs)
{
printf("small lvalue ctor\n");
}
Small(Small&& rhs)
{
printf("small rvalue ctor\n");
}
};
class Big
{
protected:
Small small;
public:
Big()
{
printf("big default ctor\n");
}
};
template<typename T>
T Call()
{
T a;
return a;
}
int main()
{
Call<Big>();
}
输出:
small default ctor
big default ctor
small rvalue ctor
2.
class Small
{
protected:
public:
Small()
{
printf("small default ctor\n");
}
Small(const Small& rhs)
{
printf("small lvalue ctor\n");
}
Small(Small&& rhs)
{
printf("small rvalue ctor\n");
}
};
class Big
{
protected:
Small small;
public:
Big()
{
printf("big default ctor\n");
}
~Big() = default;
};
template<typename T>
T Call()
{
T a;
return a;
}
int main()
{
Call<Big>();
}
输出:
small default ctor
big default ctor
small lvalue ctor
【2020-2-15】【3】C++返回值优化会对函数按值传递形参和函数局部变量优先调用移动构造函数
C++返回值优化会对函数按值传递形参和函数局部变量优先调用移动构造函数(按引用传递形参
依旧需要转换为右值引用才能获得移动优化)
除非调用std::remove_reference或类似手法压制该优化
例1:
class Small
{
protected:
public:
Small()
{
printf("small default ctor\n");
}
Small(const Small& rhs)
{
printf("small lvalue ctor\n");
}
Small(Small&& rhs)
{
printf("small rvalue ctor\n");
}
};
template<typename T>
T CallNORVO(T val)
{
return static_cast<std::remove_reference<T>::type>(val);
}
template<typename T>
T CallRVO(T val)
{
return val;
}
int main()
{
printf("Call suppress RVO\n");
CallNORVO(Small());
printf("Call dont't suppress RVO\n");
CallRVO(Small());
}
输出:
Call suppress RVO
small default ctor
small lvalue ctor
Call dont't suppress RVO
small default ctor
small rvalue ctor
例2:
class Small
{
protected:
public:
Small()
{
printf("small default ctor\n");
}
Small(const Small& rhs)
{
printf("small lvalue ctor\n");
}
Small(Small&& rhs)
{
printf("small rvalue ctor\n");
}
};
template<typename T>
T CallRef(T& val)
{
return val;
}
template<typename T>
T CallMoveRef(T& val)
{
return std::move(val);
}
int main()
{
printf("Call pass paramters by reference\n");
CallRef(Small());
printf("Call pass paramters by reference and move when return\n");
CallMoveRef(Small());
}
输出:
Call pass paramters by reference
small default ctor
small lvalue ctor
Call pass paramters by reference and move when return
small default ctor
small rvalue ctor
【2020-2-17】【1】C++ 枚举类
1.枚举类默认定义底层类型为int
2.普通枚举规则上应该按照枚举成员推导底层类型 但VC上测试都为int
3.枚举类枚举成员不支持隐式转型
例1:
enum Enum
{
Enum = 0xFFFFFFFFFFFFFFF
};
enum EnumLongLong : long long
{
EnumLongLong = 0xFFFFFFFFFFFFFFF
};
int main()
{
printf("%llx\n", Enum);
printf("%llx\n", EnumLongLong);
}
输出:
ffffffff
fffffffffffffff
例2:
enum class EnumClass
{
EnumClass = 0
};
int main()
{
EnumClass val = EnumClass::EnumClass;
int val2 = EnumClass::EnumClass;
}
编译器输出:
error C2440: “初始化”: 无法从“EnumClass”转换为“int”
【2020-2-17】【2】C++11 const_iterator支持insert与erase等操作
例:
std::vector<int> v = { 1,2,3,4,5 };
auto it_insert = v.cbegin();
for (auto it = v.cbegin(), itEnd = v.cend(); it != itEnd; ++it)
{
if (*it == 3)
{
it_insert = it;
break;
}
}
it_insert = v.erase(it_insert);
v.insert(it_insert, 30);
for (auto it = v.cbegin(), itEnd = v.cend(); it != itEnd; ++it)
{
printf("%d\n", *it);
}
输出:
1
2
30
4
5
【2020-05-11】SVN外部链接
可以使用svn:externals设置外部链接
解决svn管理目录下设置软链接目录导致svn错乱问题
首先写入一个文件 里面配置url路径与链接路径
然后执行svn propset svn:externals . -F 对应文件名
(如果不把路径配置在一个外部文件svn propset svn:externals命令会始终失败)
例:
svn.txt:
url folder
url2 folder2
cmd:
svn propset svn:externals . -F svn.txt
【2020-07-27】【1】Android Studio BuildVariants
// https://developer.android.com/studio/build/build-variants
可以通过build.gradle添加配置项
在Android Studio里通过View->ToolWindows->Build Variants打开配置窗口
【2020-07-27】【2】Android Studio断点无效问题
Android Studio使用Strip过的so调试可能会导致断点无效
通过Run->Edit Configurations里的Debugger的Symbol Directories添加
对应没有strip过的so文件路径解决
..\app\build\intermediates\cmake\debug\obj
【2020-12-31】【1】杜夫装置
通过在switch的第一个case里面插入 "while(expr){" / "do{"
并且在最后一个case里面插入 "}" / "while(expr);"
实现循环内重复case或者只break出case产生的循环
例1:
拷贝内存
int count = 15;
char source[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14};
char dest[] = { -1,-2,-3,-4,-5,-6,-7,-8,-9,-10,-11,-12,-13,-14 };
int n = (count + 7) / 8;/* count > 0 assumed */
char* from = source;
char* to = dest;
switch (count % 8)
{
case 0: do {
*to++ = *from++;
case 7: *to++ = *from++;
case 6: *to++ = *from++;
case 5: *to++ = *from++;
case 4: *to++ = *from++;
case 3: *to++ = *from++;
case 2: *to++ = *from++;
case 1: *to++ = *from++;
} while (--n > 0);
}
例2:
setjmp与longjmp模拟异常
jmp_buf env;
do
{
switch (setjmp(env))
{
case 0: while(1){
{
printf("do stuff\n");
longjmp(env, 2);
}
break;
case 1:
{
printf("exception 1\n");
}
break;
case 2:
{
printf("exception 2\n");
}
break;
} default: {
{
printf("final");
}
break;
}}
} while (0);
【2020-12-31】【2】setjmp与longjmp
// https://www.cnblogs.com/hazir/p/c_setjmp_longjmp.html
setjmp与longjmp配合使用可以实现函数间跳转
#include <setjmp.h>
int setjmp(jmp_buf env);
setjmp 函数的功能是将函数在此处的上下文保存在 jmp_buf 结构体中 以供 longjmp 从此结构体中恢复
参数 env 即为保存上下文的 jmp_buf 结构体变量
如果直接调用该函数 返回值为0
若该函数从longjmp调用返回 返回值为非0
根据函数的返回值 我们就可以知道setjmp函数调用是 第一次直接调用 还是由longjmp跳转过来的
void longjmp(jmp_buf env, int val)
longjmp 函数的功能是从 jmp_buf 结构体中恢复由 setjmp 函数保存的上下文
该函数不返回 而是从setjmp函数中返回
参数 env 是由 setjmp 函数保存过的上下文
参数 val 表示从 longjmp 函数传递给 setjmp 函数的返回值
如果 val 值为0 setjmp 将会返回1 否则返回 val
例:
jmp_buf g_env;
void test_call(int i)
{
printf("test_call %d\n", i);
longjmp(g_env, i);
}
int main()
{
int i = 0;
i = setjmp(g_env);
if (i == 10) exit(0);
while(true)
test_call(i + 1);
printf("This line does not get printed\n");
return 0;
}
输出:
test_call 1
test_call 2
test_call 3
test_call 4
test_call 5
test_call 6
test_call 7
test_call 8
test_call 9
test_call 10
【2020-12-31】【3】setjmp与longjmp配合使用可以模拟异常
// http://groups.di.unipi.it/~nids/docs/longjump_try_trow_catch.html
/* For the full documentation and explanation of the code below, please refer to
* http://www.di.unipi.it/~nids/docs/longjump_try_trow_catch.html
* See also DuffsDevice
* http://www.catb.org/jargon/html/D/Duffs-device.html
jmp_buf env;
do
{
switch (setjmp(env))
{
case 0: while(1){
{
printf("do stuff\n");
longjmp(env, 2);
}
break;
case 1:
{
printf("exception 1\n");
}
break;
case 2:
{
printf("exception 2\n");
}
break;
} default: {
{
printf("final");
}
break;
}}
} while (0);
*/
#define TRY do { jmp_buf ex_buf__; switch( setjmp(ex_buf__) ) { case 0: while(1) {
#define CATCH(x) break; case x:
#define FINALLY break; } default: {
#define ETRY break; } } }while(0)
#define THROW(x) longjmp(ex_buf__, x)
例:
const int DEFAULT_ERROR = 20;
TRY
{
printf("do stuff\n");
THROW(DEFAULT_ERROR);
}
CATCH(DEFAULT_ERROR)
{
printf("DEFAULT_ERROR\n");
}
FINALLY
{
printf("final\n");
}
ETRY;
输出:
do stuff
DEFAULT_ERROR
final
【2021-01-05】ClangAST
ClangAST是一个能够获取C/C++抽象语法树的工具
// https://www.cnblogs.com/zhangke007/p/4714245.html
// https://blog.csdn.net/qq_23599965/article/details/94595735
能够使用下面命令Dump出一个源文件的AST
clang -Xclang -ast-dump -fsyntax-only hello.cpp
也可以使用libclang打印出AST
例:
hello.cpp
struct C
{
int c;
};
struct B
{
int b;
C c;
};
struct A
{
int a;
B b;
};
/////////////////////////////////////////////
#include <stdio.h>
#include <stdbool.h>
#include <fcntl.h>
#include <string>
#include <cstdio>
#include "clang-c/Index.h"
#define DEPTH_SPACE 8
bool printPrefix(int depth)
{
for (int i = 0; i < depth * DEPTH_SPACE; ++i)
{
printf(" ");
}
for (int i = 0; i < depth; ++i)
{
printf("|");
if (i == depth - 1)
{
printf(" ");
}
}
return true;
}
bool printCursor(CXCursor cursor, int depth)
{
printPrefix(depth);
enum CXCursorKind curKind = clang_getCursorKind(cursor);
const char* curkindSpelling = clang_getCString(clang_getCursorKindSpelling(curKind));
const char* astSpelling = clang_getCString(clang_getCursorSpelling(cursor));
printf("%s ", curkindSpelling);
CXSourceRange range = clang_getCursorExtent(cursor);
CXSourceLocation startLocation = clang_getRangeStart(range);
CXSourceLocation endLocation = clang_getRangeEnd(range);
CXFile file;
unsigned int line, column, offset;
clang_getInstantiationLocation(startLocation, &file, &line, &column, &offset);
printf("<line:%u column:%u", line, column);
printf(", ");
clang_getInstantiationLocation(endLocation, &file, &line, &column, &offset);
printf("line:%u column:%u>", line, column);
printf(" %s ", astSpelling);
puts("");
return true;
}
enum CXChildVisitResult printVisitor(CXCursor cursor, CXCursor parent, CXClientData client_data)
{
const char* astSpelling = clang_getCString(clang_getCursorSpelling(cursor));
int depth = *(int*)client_data;
printCursor(cursor, depth);