- strange issue ... - 16 Updates
- Question on "range-for-statement" - 3 Updates
- alloca()-support - 3 Updates
- On endianness, many #ifdefs, and the need thereof - 3 Updates
Sam <sam@email-scan.com>: Oct 03 07:00AM -0400 Bonita Montero writes: >> read and return, so the program cannot physically work. ... > I know the reasons why this doesn't work. > I only wanted to have a workaround without making ABC static. There is no "workaround". C++ does not work this way. If something is a class member, it can only exist as an instance of the class. Therefore you can only access it as a member of an instance of the class. It is not an independent object, with a life of its own. End of story. |
James Kuyper <jameskuyper@alumni.caltech.edu>: Oct 03 06:25AM -0700 On Thursday, October 3, 2019 at 5:16:14 AM UTC-4, Bonita Montero wrote: > > There is no A object created anywhere, so there is no existing ABC > > member to read and return, so the program cannot physically work. ... > I know the reasons why this doesn't work. If so, then it was counter-productive to start your first message in this thread with the question "Why doesn't this work?" > I only wanted to have a workaround without making ABC static. Well, the simple, obvious solution is to make ABC static. I can't imagine why it's important to you that it not be static. If you do have a good reason for that requirement, you should explain the reason, so people can better help you. In the meantime, the following approach meets your stated requirement: int const ABC = 123; struct A { struct B { int f(); }; }; So does the following: struct A { struct B { int const ABC = 123; int f(); }; }; But those solutions are so obvious that I assume that they violate some additional requirements that you failed to mention. If so, you need to explain all the relevant requirements, so people will be better able to help you. |
Bonita Montero <Bonita.Montero@gmail.com>: Oct 03 03:41PM +0200 > additional requirements that you failed to mention. If so, you need to > explain all the relevant requirements, so people will be better able to > help you. I need the constant in the outer class. With static I found a bug in the gcc, that I couln't use the constant in the constructor. The constants were defined this way: static std::uint32_t const UNPINNED_NODE = 0, FREE_NODE = 0xFFFFFFFFu; I assigned FREE_NODE to a member in this way. nd->pinCounter = (uint32_t const)FREE_NODE; // gcc-bug? Without the cast I got a linker-error (MSVC compiled the code). Surprisingly all other "accesses" to FREE_NODE in the outer class didn't give this linker-error. I don't know why gcc acesses FREE_NODE like it's not a const at this point in the constructor. So I asked for a work-around bcause I needed the constant in the innner class as well in the outer. |
Paavo Helde <myfirstname@osa.pri.ee>: Oct 03 05:02PM +0300 On 3.10.2019 16:41, Bonita Montero wrote: > like it's not a const at this point in the constructor. So I asked for > a work-around bcause I needed the constant in the innner class as well > in the outer. Your problem is explained here: https://isocpp.org/wiki/faq/ctors#link-errs-static-data-mems https://isocpp.org/wiki/faq/ctors#static-const-with-initializers And no, it's not a bug in gcc. |
Bonita Montero <Bonita.Montero@gmail.com>: Oct 03 04:07PM +0200 > Your problem is explained here: > https://isocpp.org/wiki/faq/ctors#link-errs-static-data-mems That's a different problem because it's not about static const members. > https://isocpp.org/wiki/faq/ctors#static-const-with-initializers > And no, it's not a bug in gcc. I tried defining the member within one translation-unit, but this didn't help. And if I removed the line I quoted accessed to FREE_NODE by ohter methods of my class weren't complained by gcc. |
Bonita Montero <Bonita.Montero@gmail.com>: Oct 03 04:13PM +0200 > I tried defining the member within one translation-unit, but this didn't > help. And if I removed the line I quoted accessed to FREE_NODE by ohter > methods of my class weren't complained by gcc. And read-access to FREE_NODE is compile-time constant anyway. Only if I nonsensically cast FREE_NODE to non-const and assign ít a value there should be a linker-error. |
Paavo Helde <myfirstname@osa.pri.ee>: Oct 03 05:18PM +0300 On 3.10.2019 17:07, Bonita Montero wrote: >> https://isocpp.org/wiki/faq/ctors#link-errs-static-data-mems > That's a different problem because it's not about static const members. >> https://isocpp.org/wiki/faq/ctors#static-const-with-initializers The second link is specifically about static const members. Quoting from there: "And, just like other static data members, it must be defined in exactly one compilation unit, though this time without the = initializer part" >> And no, it's not a bug in gcc. > I tried defining the member within one translation-unit, but this didn't > help. Then you did something wrong. > And if I removed the line I quoted accessed to FREE_NODE by ohter > methods of my class weren't complained by gcc. Such linker related bugs in your code are "no diagnostic required". |
Bonita Montero <Bonita.Montero@gmail.com>: Oct 03 04:36PM +0200 > there: > "And, just like other static data members, it must be defined in exactly > one compilation unit, though this time without the = initializer part" That's not alway true. The have to be declared only if they're written or read. But if they're compile-time-constant like my uint32_t, they are neither. >> I tried defining the member within one translation-unit, but this didn't >> help. > Then you did something wrong. No, I didn't >> And if I removed the line I quoted accessed to FREE_NODE by ohter >> methods of my class weren't complained by gcc. > Such linker related bugs in your code are "no diagnostic required". No, that's a clear sign that gcc has a bug at this point. At other placess FREE_NODE is compile-time-constant but in the constructor it is physically accessed. |
Bonita Montero <Bonita.Montero@gmail.com>: Oct 03 05:15PM +0200 > Your problem is explained here: > https://isocpp.org/wiki/faq/ctors#link-errs-static-data-mems > https://isocpp.org/wiki/faq/ctors#static-const-with-initializers // Fred.h class Fred { public: private: static int j_; }; // Fred.cpp #include "Fred.h" int Fred::j_ = some_expression_evaluating_to_an_int; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ That's not ncessary because Fred::j_ is compile-time constant. |
Bo Persson <bo@bo-persson.se>: Oct 03 05:28PM +0200 On 2019-10-03 at 16:36, Bonita Montero wrote: > No, that's a clear sign that gcc has a bug at this point. At other > placess FREE_NODE is compile-time-constant but in the constructor > it is physically accessed. No, the bug is in your code. The separate definition is formally required (at least in older C++). However, the optimizer might often remove all references to the constant, and then the linker will not notice that it is missing and let you get away with it. This case is so common that most people probably belive it is the norm. Bo Persson |
Bonita Montero <Bonita.Montero@gmail.com>: Oct 03 05:32PM +0200 >> it is physically accessed. > No, the bug is in your code. > The separate definition is formally required (at least in older C++). No, the separate definition is not required if it can be evaluated to a compile-time constant. You can even define arrays with compile-time sizes on those const-members. |
Bonita Montero <Bonita.Montero@gmail.com>: Oct 03 05:35PM +0200 > However, the optimizer might often remove all references to the > constant, and then the linker will not notice that it is missing > and let you get away with it. Consider this: int const ABC = 123; int fABC() { return ::ABC; } If I compile it without optimizations with MSVC++, I'll get this: mov eax, 123 ret 0 And gcc compiles this without optimizations: pushq %rbp movq %rsp, %rbp movl $123, %eax popq %rbp ret |
Bo Persson <bo@bo-persson.se>: Oct 03 05:46PM +0200 On 2019-10-03 at 17:32, Bonita Montero wrote: > No, the separate definition is not required if it can be evaluated to > a compile-time constant. You can even define arrays with compile-time > sizes on those const-members. Quoting myself: "However, the optimizer might often remove all references to the constant, and then the linker will not notice that it is missing and let you get away with it. " In C++17 you can use constexpr instead of const, and formally get away from the requirement for a separate definition. You might want to read the last paragraph on this page: https://en.cppreference.com/w/cpp/language/static "If a static data member is declared constexpr, it is implicitly inline and does not need to be redeclared at namespace scope. This redeclaration without an initializer (formerly required as shown above) is still permitted, but is deprecated. (since C++17)" Bo Persson |
Bonita Montero <Bonita.Montero@gmail.com>: Oct 03 06:55PM +0200 > "However, the optimizer might often remove all references to the > constant, and then the linker will not notice that it is missing > and let you get away with it. " No, that's not a matter of the optimizer. The language itself imposes that a const variable has to be compile-time constant unter certain cirtcumstances. Without that the following wouldn't be possible: size_t const ARRAY_SIZE = 123; int array[ARRAY_SIZE]; How could that be possible if this would be a matter of the optimizer? |
Paavo Helde <myfirstname@osa.pri.ee>: Oct 03 08:32PM +0300 On 3.10.2019 19:55, Bonita Montero wrote: > size_t const ARRAY_SIZE = 123; > int array[ARRAY_SIZE]; > How could that be possible if this would be a matter of the optimizer? Exactly, this line is the *definition* of a constant, providing a linker symbol if needed. What you can have inside a class is just a *declaration*. If you acknowledge the above ARRAY_SIZE definition as valid code, then why do you refuse to provide a similar definition for your const static class member? |
Bonita Montero <Bonita.Montero@gmail.com>: Oct 03 07:35PM +0200 >> How could that be possible if this would be a matter of the optimizer? > Exactly, this line is the *definition* of a constant, providing a linker > symbol if needed. What you can have inside a class is just a *declaration*. The actual discussion was whether the optimization is a matter of the language or of the optimizer. We were not discussion definitions vs. declarations at this point. > If you acknowledge the above ARRAY_SIZE definition as valid code, then > why do you refuse to provide a similar definition for your const static > class member? Because it is not necessary from what the language allows. |
Joseph Hesse <joeh@gmail.com>: Oct 03 09:03AM -0500 I am puzzled how the following program works. ===================================================== #include <iostream> using namespace std; int main() { char x[] = {"Hello"}; // x is a 0 terminated character array for(const auto &i : x) cout << i << " "; cout << "\n"; } ===================================================== Putting a 0 at the end of a character array to indicate the end is a convention and not part of the language. There are library functions that understand this convention but the library is not part of the language definition. How does the range-for-statement, which is a language construct, know that it has to stop when it sees a 0? Thank you, Joe |
Paavo Helde <myfirstname@osa.pri.ee>: Oct 03 05:12PM +0300 On 3.10.2019 17:03, Joseph Hesse wrote: > language definition. > How does the range-for-statement, which is a language construct, know > that it has to stop when it sees a 0? It doesn't know and it doesn't stop at any zero byte. Instead, it knows the size of the x array. #include <iostream> using namespace std; int main() { char x[] = { "Hello\0\0World" }; for (const auto &i : x) cout << int(i) << " "; cout << "\n"; } 72 101 108 108 111 0 0 87 111 114 108 100 0 |
Keith Thompson <kst-u@mib.org>: Oct 03 10:21AM -0700 > language definition. > How does the range-for-statement, which is a language construct, know > that it has to stop when it sees a 0? It doesn't. When I compile and run your program, the output *looks like* H e l l o but in fact it prints the null character: ./c | cat -A H e l l o ^@ $ As Paavo Helde correctly states, it knows the size of the array, not the length of the string contained in the array. -- Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst> Will write code for food. void Void(void) { Void(); } /* The recursive call of the void */ |
scott@slp53.sl.home (Scott Lurndal): Oct 03 01:23PM >Buf [A-1] = B; >return (A + B * D - C); >} 00000000004004f0 <Funz>: 4004f0: 55 push %rbp 4004f1: 48 89 e5 mov %rsp,%rbp 4004f4: 53 push %rbx 4004f5: 48 83 ec 38 sub $0x38,%rsp // Reserve frame 4004f9: 89 7d cc mov %edi,-0x34(%rbp) 4004fc: 89 75 c8 mov %esi,-0x38(%rbp) 4004ff: 48 89 e0 mov %rsp,%rax 400502: 48 89 c6 mov %rax,%rsi 400505: c7 45 ec 03 00 00 00 movl $0x3,-0x14(%rbp) 40050c: 8b 45 cc mov -0x34(%rbp),%eax 40050f: 48 63 f8 movslq %eax,%rdi 400512: 48 83 ef 01 sub $0x1,%rdi 400516: 48 89 7d e0 mov %rdi,-0x20(%rbp) 40051a: 48 63 f8 movslq %eax,%rdi 40051d: 49 89 f8 mov %rdi,%r8 400520: 41 b9 00 00 00 00 mov $0x0,%r9d 400526: 48 63 f8 movslq %eax,%rdi 400529: 48 89 fa mov %rdi,%rdx 40052c: b9 00 00 00 00 mov $0x0,%ecx 400531: 48 98 cltq 400533: 48 c1 e0 02 shl $0x2,%rax 400537: 48 8d 50 03 lea 0x3(%rax),%rdx 40053b: b8 10 00 00 00 mov $0x10,%eax 400540: 48 83 e8 01 sub $0x1,%rax 400544: 48 01 d0 add %rdx,%rax 400547: bb 10 00 00 00 mov $0x10,%ebx 40054c: ba 00 00 00 00 mov $0x0,%edx 400551: 48 f7 f3 div %rbx 400554: 48 6b c0 10 imul $0x10,%rax,%rax 400558: 48 29 c4 sub %rax,%rsp // Allocate Buf[A] 40055b: 48 89 e0 mov %rsp,%rax // %rax = &Buf[0] 40055e: 48 83 c0 03 add $0x3,%rax // dword align pointer 400562: 48 c1 e8 02 shr $0x2,%rax 400566: 48 c1 e0 02 shl $0x2,%rax 40056a: 48 89 45 d8 mov %rax,-0x28(%rbp) // Save Buf addr in frame 40056e: c7 45 d4 02 00 00 00 movl $0x2,-0x2c(%rbp) 400575: 8b 45 cc mov -0x34(%rbp),%eax 400578: 8d 50 ff lea -0x1(%rax),%edx 40057b: 48 8b 45 d8 mov -0x28(%rbp),%rax 40057f: 48 63 d2 movslq %edx,%rdx 400582: 8b 4d c8 mov -0x38(%rbp),%ecx 400585: 89 0c 90 mov %ecx,(%rax,%rdx,4) 400588: 8b 45 c8 mov -0x38(%rbp),%eax 40058b: 0f af 45 d4 imul -0x2c(%rbp),%eax 40058f: 89 c2 mov %eax,%edx 400591: 8b 45 cc mov -0x34(%rbp),%eax 400594: 01 d0 add %edx,%eax 400596: 2b 45 ec sub -0x14(%rbp),%eax 400599: 48 89 f4 mov %rsi,%rsp 40059c: 48 8b 5d f8 mov -0x8(%rbp),%rbx 4005a0: c9 leaveq 4005a1: c3 retq |
David Brown <david.brown@hesbynett.no>: Oct 03 03:38PM +0200 On 03/10/2019 13:39, Soviet_Mario wrote: > the code I'd like to see in .asm intermediate code (NO OPTIMIZATION > ACTIVE) was Examining generated assembly code with no optimisation is usually pointless. If you care about the efficiency of the assembly, you will have optimisation enabled on the compiler. Looking at the assembly generated with optimisation off tells you practically nothing. The tool you want here is the webpage <https://godbolt.org>. It is an online compiler site, letting you type small bits of code and compile it with a wide variety of compilers ("x86-64 gcc (trunk)" is popular, but not the only choice) and using whatever options you want (like "-x c -std=c11 -O2 -Wall -Wpedantic" as a reasonable starting point). Use that site to see the generated code, and perhaps these newsgroups to ask /why/ you get particular code. It's better than asking people in these groups to compile code snippets for you, at least for standard compilers. |
scott@slp53.sl.home (Scott Lurndal): Oct 03 02:51PM >pointless. If you care about the efficiency of the assembly, you will >have optimisation enabled on the compiler. Looking at the assembly >generated with optimisation off tells you practically nothing. Although the example he provided optimizes (-O3) down to: 0000000000400400 <main>: 400400: b8 07 00 00 00 mov $0x7,%eax 400405: c3 retq |
scott@slp53.sl.home (Scott Lurndal): Oct 03 01:17PM >64, 128 bit floating point numbers, in either little endian or big endian. >Could you explain the "obvious endian independent method" that will encode and >decode that? If the incoming big-endian data is treated as a sequence of bytes, you can easily reconstruct a binary value simply shifting the data into the correct sized container a byte at a time. uint64_t value = 0ul; char *bp = &buffer[first_byte_of_uint64_big_endian_data]; for (size_t i = 0; i < sizeof(uint64_t); i++) { value <<= 8; value |= *bp++; } This works regardless of the host endianness. |
David Brown <david.brown@hesbynett.no>: Oct 03 04:03PM +0200 On 03/10/2019 15:17, Scott Lurndal wrote: > value |= *bp++; > } > This works regardless of the host endianness. You want "uint8_t" (or, for even more portability, uint_least8_t) instead of "char" for your pointer. Unpleasant things will happen if "char" is signed. Apart from that, that is the "obvious" method I meant. Some compilers are smart enough to optimise this kind of code into a single load (if the cpu supports unaligned accesses) and a byte-swap (if the cpu is little-endian). Clang manages it for 16-bit and 32-bit versions of this code, but not the 64-bit version. gcc won't do it at all in this case (I've seen it do such optimisation with other code). |
Daniel <danielaparker@gmail.com>: Oct 03 07:13AM -0700 On Thursday, October 3, 2019 at 10:03:52 AM UTC-4, David Brown wrote: > instead of "char" for your pointer. Unpleasant things will happen if > "char" is signed. > Apart from that, that is the "obvious" method I meant. Thanks, Scott and David, obvious, perhaps, but I didn't know about it. Daniel |
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page. To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com. |
No comments:
Post a Comment