constants Array scope in "C'" - Page 1
Forum section: electronics / general

author: gogoman
author_rank: Regular Contributor
timestamp: December 26, 2018, 05:16:43 pm
content: Hi I need to use a constant array, Since the array is accessed by several functions it ended up in global space.Under what conditions should constants be declared in global space?If the constant is declared in main or in a function does it need to be declared as static?Execution Speed is a concern, is there a benefit between local vs global scope?thanks

author: 0xdeadbeef
author_rank: Super Contributor
timestamp: December 26, 2018, 05:50:41 pm
content: In C, the "const" classifier originally just means that the value can't be changed after initialization. So the treatment of "const" depends on the compiler or its settings.For a PC compiler, "const" just means that the compiler may optimize these values, i.e. they may not even appear in the mapfile anymore since the compiler replaced the const access by immediate values.Forembedded compilers, there's at least a setting to put "const" values in ROM. This saves RAM and the copy of ROM to (initialized) RAM in the C runtime init isn't needed anymore.So embedded programs tend to put data in ROM sections to save RAM. However, usually (S)RAM is faster than (Flash) ROM, so this typically comes at the cost of execution speed.Using const arrays in a function (without static) usually means that the array is located on the stack and has to be initialized during runtime every time the function is called. So this is typically a bad idea.Anyway, if execution speed is a concern, don't put lookup tables etc. in ROM.

author: hans
author_rank: Super Contributor
timestamp: December 26, 2018, 09:02:24 pm
content: Short answer: depends on compiler, architecture and settingsLonger answer:Const means that the variable can only be assigned once and is then read-only. This does not mean that the compiler will put these variables in ROM. For example:Code:int foo(void) {static uint8_t i = 0;const uint8_t j = i*i;return j;}Will compile to a short assembly, as it always returns 0, despite variable i being marked static (keeps state across calls).If you do change i, the compiler will still let variable j be marked "const" even though it needs to be calculated in run-time:Code:int foo(void) {static uint8_t i = 0;const uint8_t j = i*i;i++;return j;}This generates a lot of assembly code. If you want the compiler to truly evaluate as much expressions as possible during compilation (and otherwise throw an error), you could use C++'s constexpr instead of const. If you would change that for the code above, you would get an error:Code:<source>:5:29: error: the value of 'i' is not usable in a constant expressionconstexpr uint8_t j = i*i;As it is indeed not intended..In this case, "constexpr" is a quality of life thing. If you're using C, the best thing is to keep the code simple (as is always the case) and just assign const values to the array you've got.The placement of the table may influence the address of the table in the code space. A compiler may be more tempted to put a global variable at the end of the program, after the code region(s). Typically what I see in ARM GCC is that it will also put constants nearby functions, for example 32-bit pointer locations, and then load data from it by relative positioning of PC register. In addition, as most ARM micro's use FLASH accelerators/cache, the spatial locality of these constants may help in reducing the number of random accesses to FLASH.However if you put the same array in multiple functions, the compiler will likely put these arrays multiple times in your binary.It also depends on your program if this is a big penalty hit. You could speed up the execution by processing samples in blocks, such that the constants only need to be loaded once for multiple samples.

author: JPortici
author_rank: Super Contributor
timestamp: December 26, 2018, 09:49:25 pm
content: Quote from: 0xdeadbeef on December 26, 2018, 05:50:41 pmFun fact, with the Mikro C compiler for microchip PIC it used to be that when you declared a const variable the compiler would- Allocate the space in ROM to hold the data- And also allocate the space in RAM to hold a copy of the data, you would operate to the RAM copyYes, the compiler isn't free, it has a limit on how much ROM/RAM you can use in free mode. Now, i wonder why they decided to operate this wayYes, if you tried to change the variable in C the compiler would throw an error. Never tried to debug to see if i could change it at runtime because i needed their debuggers, they didn't support the pickits at that time

author: helius
author_rank: Super Contributor
timestamp: December 26, 2018, 10:09:45 pm
content: Quote from: gogoman on December 26, 2018, 05:16:43 pmWhat you're calling "global space" is formally known astop-level scope. This is a scope that is visible from the point of declaration to the end of the file. As mentioned above,constis a type qualifier and is not related to the scope in which an identifier is visible.constrestricts what can be done to the object, not where it can be seen.Along with scope is the issue ofextent, the time during which the object is defined. Objects can have either local or static extent, which is related to the place they are allocated in memory. Local extent objects are calledautomaticand are allocated on the stack, in the current stack frame. Each time the block is executed, they are initialized in the top frame of the stack. When their enclosing block is exited, they are deallocated as the top frame of the stack is discarded. Static extent objects, by contrast, are allocated in a permanent location (called the Data segment) and remain there for the entire program execution. All top-level declarations have static extent, as do local (block) declarations with thestaticstorage class specifier.A different, related, issue is linker visibility. The object that you declare in top-level scope can be truly local to its own file, or made visible ("exported") to the linker so it can be seen in other files, as well. When the storage classstaticis used on the top-level declaration, it ensures that only its own file can see it. Ifstaticis not used, the storage class defaults toexternwhich is made visible to other files via the linker. The only way thatexternis literally typed in is for declarations thatreferto a definition in another file. So the three cases for linker visibility are:nothing - external and defined by this fileextern- external and defined in another filestatic- internalQuoteConstants should be defined with static extent, as that ensures they are initialized at load time only. Both top-level declarations, and local declarations withstatichave static extent. The choice depends on whether the object must be visible in more than one function's scope.QuoteSee above—declaring an object asstaticensures it has static extent.QuoteFor maximum execution speed, compile with optimizations; this will often inline the constant values in the instructions so they do not require memory accesses. Memory for local vs global scope are accessed at the same speed on most machine architectures.

author: westfw
author_rank: Super Contributor
timestamp: December 27, 2018, 03:30:31 am
content: QuoteAVR compilers do the same thing. It's pretty much REQUIRED by the Harvard Architecture used by those microcontrollers - code can not access ROM data in the same way that it accesses RAM data - it best, it takes different instructions, and you need two copies of functions like "strcpy(dst, src)" depending whether "src" is in RAM or ROM. (also, you usually lack whatever fancy addressing modes might be available for RAM, when accessing the ROM...)

author: JPortici
author_rank: Super Contributor
timestamp: December 27, 2018, 07:02:05 am
content: Never really been a problem for PICs (modified harvard)- Since at least the 16F84A you had a RETLW instruction. Microchip put code in the datasheet on how to make lookup tables with a branch to a relative address and a sequence of RETLWs. It gets more complicated with 16 bit, but it would be anyway because 8 bit core- when they added self-programming you could also read the whole program word, so not only 8 bit but 14/16/24/32 depending on architecture with pre or post increment- I think you can also use the indirect registers to point to flash in the latest PIC16/PIC18- 16 bit parts can map the upper 32k of memory to blocks of flash memory or blocks of RAM. It only takes more cycles to access flash- 32 bit parts have the address translator that points to flash or ram, whateverPICs don't really need to copy ROM to RAM to make constants... devices with an handful of RAM but a shitload of flash can't have that luxury

author: westfw
author_rank: Super Contributor
timestamp: December 27, 2018, 09:56:34 am
content: Quoteyeah, yeah. You can read flash. But NOT the same way you read data ram. If you were writing strcpy(), you needed to know ahead of time which type of memory you were accessing. You can't pass "&x" to a function and have it work regardless of whether x is in flash or RAM...QuoteI don't think so. Seems especially unlikely, with a 2Mb flash address space (on PIC18; 64k on PIC16, I think) and only 8k/4k of RAM and 16bit "indirect registers."I can't comment on the 16bit PICs.PIC32 has the whole MIPS 32bit unified address space, so it doesn't have any problems with data in flash. I'm pretty sure that "const" is all you need to put variables in flash, on PIC32.

author: NorthGuy
author_rank: Super Contributor
timestamp: December 27, 2018, 10:27:26 pm
content: Quote from: westfw on December 27, 2018, 09:56:34 amThe XC8 PIC compiler actually allows you to do this. You may have universal pointers which can point anywhere - the compiler furnish the correct function in all cases - even if it needs to select it at run-time.On the other hand, PIC24/dsPIC33 have a feature called Program Space Visibility (PSV) which lets you map a selected part of the Code address space into the Data address space. This way you can access flash and RAM with the same strcpy(). Of course, you cannot write flash this way.

author: gogoman
author_rank: Regular Contributor
timestamp: January 03, 2019, 02:50:59 pm
content: "Along with scope is the issue of extent, the time during which the object is defined. Objects can have either local or static extent, which is related to the place they are allocated in memory. Local extent objects are called automatic and are allocated on the stack, in the current stack frame. Each time the block is executed, they are initialized in the top frame of the stack. When their enclosing block is exited, they are deallocated as the top frame of the stack is discarded. Static extent objects, by contrast, are allocated in a permanent location (called the Data segment) and remain there for the entire program execution. All top-level declarations have static extent, as do local (block) declarations with the static storage class specifier."Hi, thanks you for all the replies a few more questions. forgive me if I'm being redundantif the object is used by other functions is there a reason not to declare the object in main as a static constant?For functions which use this object is it standard practice to pass the object to the function using a pointer?

author: NorthGuy
author_rank: Super Contributor
timestamp: January 03, 2019, 03:22:50 pm
content: Quote from: gogoman on January 03, 2019, 02:50:59 pmThere's no such thing as static constant in C. They're all variables. The variables declared with "const" cannot be changed by the programmer (that is they're read only), but it is possible for them to change due to external causes. The keyword which determines whether external forces can change your variable is "volatile".The C compiler for MCUs often hijack the "const" keyword interpreting it as "located in flash". This is not standard in C and you must read the documentation for your particular compiler.There are also constant expressions (whose result is known at compile time). Note they are expressions, not a variables. They aren't stored anywhere at run time, most likely get embedded in the code by the compiler.Quote from: gogoman on January 03, 2019, 02:50:59 pmTypical reasons why you would want to pass a pointer (as opposed to value) might be:- the function may change the object being passed- the size of the object may vary- the object is too big to be passed directly

author: BloodyCactus
author_rank: Frequent Contributor
timestamp: January 03, 2019, 06:15:23 pm
content: 'volatile' is more, dont cache this content. Since C is half pass by ref and half pass by val. Say, using a value in an inner loop, each read of the variable in that tight loop wont be updated, but if volatile, it will be updated. (ie: clock ticks incremented in an isr).const can be a pain, lots of old C code abused const, some compilers would be const data into the read only text segment, some i the data segment, I've seen lot of old C modify a string that one compiler had in data, another put in text and thus read only.Quote from: NorthGuy on January 03, 2019, 03:22:50 pmstatic is a storage class, so you can have a static const, static just means 'visible only within this file'. its about scope. a static const just makes that function or variable visibile to other functions within that same C file.

author: ggchab
author_rank: Frequent Contributor
timestamp: January 04, 2019, 12:34:45 pm
content: Quote from: westfw on December 27, 2018, 09:56:34 amI am programming PIC24 and dsPIC33 and I think it's the role of the PSV window to give access to 32K of ROM as if it was RAM. I use "&x" to pass "const" (stored in flash) and "non const" variables to the same function.On some PIC (at least 12F1822), FSR registers may be used to access the program flash memory.

author: 0xdeadbeef
author_rank: Super Contributor
timestamp: January 04, 2019, 01:10:13 pm
content: For the record: in the automotive world, the calibration data (calibration maps, constants etc.) is put in a const section and there are several approaches used to map this Flash/ROM section to RAM during development.In former times with external ROM e.g. the uppermost address line was used to select an external RAM. With today's 32bit microcontrollers, usually the MMU is used to switch between internal Flash and external RAM. But there are some automotive microcontrollers like the Infineon Tricore/Aurix and the Renesas RH850 E2x which still don't support an MMU, so they have some special overlay registers to map internal RAM over Flash.For the production devices, the internal RAM is not nearly sufficient to cover all the calibration data (multiple Megabytes nowadays), so there are some specific "emulation devices" which cost like 1k€ and have a few additional MB of embedded RAM to mirror the calibration ROM.That's why embedded compilers used in the automotive world always have to include an option that forbids any optimization for const sections. Note in this context that usually you can't declare a variable constandvolatile, as this doesn't any make sense in standard C. Most compilers should complain about this and static code checkers like PC-Lint should do so as well.

author: NorthGuy
author_rank: Super Contributor
timestamp: January 04, 2019, 03:27:17 pm
content: Quote from: westfw on December 27, 2018, 09:56:34 amXC8 compiler selects the size for the pointer. Different pointers may be of different size - from 1 to 3 bytes. XC8 analyzes what the pointer can point to and selects accordingly. They call it "omniscient code generation". It's a lot of work to make C concepts to work on PIC16/18.If I remember correctly, the earlier compiler - C18, required you to specify where your pointer points to data or to flash. I would actually prefer this over what XC8 is doing.Quote from: westfw on December 27, 2018, 09:56:34 amXC16 and XC32 are different from XC8 and are GCC based.

author: dmills
author_rank: Super Contributor
timestamp: January 04, 2019, 08:15:44 pm
content: Quote from: 0xdeadbeef on January 04, 2019, 01:10:13 pmActually volatile const is a perfectly valid construct in embedded C.volatile - value may be modified from outside the C execution context.const - value cannot be modified from within the C execution context.So something like a read only peripheral status register makes perfect sense as a pointer to a volatile const object.Granted your MISRA tool will throw a fit, but that sort of low level driver stuff tends to need a set of documented exceptions anyway.Regards, Dan.

author: 0xdeadbeef
author_rank: Super Contributor
timestamp: January 04, 2019, 08:23:05 pm
content: What I meant is that a variable can't be constant and volatile and the same time.Constpointersare a special breed though. It matters a lot if theaddressis constant or thevaluethe pointer points to. This is decided by the location of the const qualifier in the definition.Most embedded developers aren't fully aware of that and just put the constsomewherewhich again lots of compilers still accept due to special settings for const handling. Still, combining const and volatile without knowing what you do can lead to extremely surprising results. Just had to deal with this end of last year.

author: janoc
author_rank: Super Contributor
timestamp: January 04, 2019, 08:28:25 pm
content: Quote from: westfw on December 27, 2018, 03:30:31 amErm, nope. If you want to put/access something in ROM (= Flash) on AVRs, you need to tag the pointer/variable using PROGMEM.Declaring somethingconstis not enough - and it makes no sense neither, becauseconstonly means that you can't change the value usingthat particular name. I.e. you can have a variable and two pointers at it, one const, one non const and it is completely legal C - you can freely change that value using the non const pointer and there is no problem (whether or not it is a good programming style is another discussion). You can also cast the "constness" away and modify the value at will (again, let's not go into the issues of a good programming style). Again a completely legal operation (in fact, C++ has even a special cast operator just for this:const_cast).All that would break if the compiler made assumptions about where to store the data. GCC is actually standard compliant compiler, unlike that Mikro C.

author: charliex
author_rank: Frequent Contributor
timestamp: January 04, 2019, 08:33:15 pm
content: a variable can be const and volatile at the same time, for instance a hardware clock/timer/counter, it just means it is read only and for the compiler to handle it properly, not that the value never changes. it doesn't need to be a pointer since you can specify where the variable exists with a linker script or extension.

author: 0xdeadbeef
author_rank: Super Contributor
timestamp: January 04, 2019, 08:54:14 pm
content: Quote from: charliex on January 04, 2019, 08:33:15 pmI'm not sure if your timer example is valid.IMHO, standard C assumes a "const" variable to never alter its value during runtime. So it's not only "read only" but "constant" - hence the name.Actually I would be surprised if you could define a const variable without assigning it a value. IMHO this is different to the similar qualifier "final" in Java which allows a single write access after the actual definition.Plus I'm convinced that non-embedded C compilers will replace const variables with immediate values in higher optimization levels.Anyway, I never saw an example of peripheral registers being mapped to the correct address through linker scripts. Actually several linkers/locators I worked with won't allow this for a specific variable but only for a section. So you'd need a section for each peripheral register which is somewhat nuts. Besides it would be just a linker trick and has nothing to do with C syntax. So the C compiler would still need the initialization value for your constant and write that over your read only timer one way or the other.

author: andersm
author_rank: Super Contributor
timestamp: January 04, 2019, 09:02:30 pm
content: Quote from: 0xdeadbeef on January 04, 2019, 08:54:14 pmIt is straight from the C standard. §6.7.3, page 109 in the C99 TC3 final draft:Quote

author: NorthGuy
author_rank: Super Contributor
timestamp: January 04, 2019, 09:33:28 pm
content: Quote from: 0xdeadbeef on January 04, 2019, 08:54:14 pmThe whole point of the standard is to define things as clearly as possible, so it would be impossible to have an opinion which is different from what the standard describes.

author: janoc
author_rank: Super Contributor
timestamp: January 04, 2019, 10:14:49 pm
content: Quote from: NorthGuy on January 04, 2019, 09:33:28 pmThe problem isn't the standard but the fact that many people who are arguing about it have never read it. The actual text costing about $30 isn't helping the situation.And 0xdeadbeef's opinion is wrong, the standard doesn't "assume" anything such. Look for yourself:http://www.dii.uchile.cl/~daespino/files/Iso_C_1999_definition.pdf(p. 108, type qualifiers).It just says that if you try to access a const qualified object using a non-const lvalue, the results are undefined (i.e. implementation dependent). It also says that an implementationmay(but doesn't have to) place const but not volatile objects into read-only storage. And that's pretty much all that there is on const in the standard.

author: cv007
author_rank: Frequent Contributor
timestamp: January 04, 2019, 10:46:23 pm
content: One example of using 'const volatile' is if a flash constant is updated via a flash write (flash storage for settings when eeprom not available, for example)- you just told the compiler you can't write to it, but you better read it when we ask for its contents since it may have changed without your knowledge (from a flash write, which the compiler will not know about).

author: 0xdeadbeef
author_rank: Super Contributor
timestamp: January 05, 2019, 12:22:54 am
content: OK, you got me there. I guess we can agree though that the standard is (again) pretty vague here but I must admit I'm surprised that it really names the "const volatile" example.I still think it's an obscure case and it would have been better to forbid it as there is no real use to something like this when you can as well use a const pointer.Anyway, I would avoid something like this like the plague for portability and robustness.E.g. I'm pretty sure though that the compiler I currently work with in our latest project throws a compiler error if you try to define something as volatile and const.It also optimizes most volatile const pointers to registers by replacing them with immediate values.Then again, it also complains about other things that I would assume to be correct (const pointer to const value).

author: NorthGuy
author_rank: Super Contributor
timestamp: January 05, 2019, 01:22:32 am
content: Quote from: 0xdeadbeef on January 05, 2019, 12:22:54 amHow's that obscure? You have a variable which is writable by some other thread, but is read only on your end. You declare it "const volatile". Now the compiler will not let you write it and will also ensure that it gets re-fetched every time you use it. How else would you do it?The "const" keyword simply doesn't mean "constant", even though many people in this thread see them as interchangeable.

author: NorthGuy
author_rank: Super Contributor
timestamp: January 05, 2019, 01:25:58 am
content: Quote from: janoc on January 04, 2019, 10:14:49 pmAre you suggesting that a person who didn't read the standard is entitled to have his own opinion?

author: westfw
author_rank: Super Contributor
timestamp: January 05, 2019, 09:51:51 am
content: Quoteyes; no argument there. The OP and I were talking about initialized variables declared as const but NOT explicitly placed in PROGMEM/Flash, which result in a RAM variable AND a ROM location that holds the initialization value, on both PIC8 and AVR. The ROM value is copied to the RAM variable during the C startup code.

author: 0xdeadbeef
author_rank: Super Contributor
timestamp: January 05, 2019, 10:18:02 am
content: Quote from: NorthGuy on January 05, 2019, 01:22:32 amWell, "const volatile" should not work for this case. If you want to write to a variable from another thread, you need to declare it in a header. You need to use exactly the same qualifiers there which means the other thread can't write to it either. The only workaround is cheating, i.e. declare it non-const in another module but this is a direct way into linker/locator and consistency issues and won't survive any proper code review (or static code analysis which works on a project scope).Quote from: NorthGuy on January 05, 2019, 01:22:32 amA variable that is only declared "const" isconstantfor sure (can't be changed after initialization). The only surprise is that the standard allows the "volatile" and "const" qualifiers at the same time which seem to contradict each other. So this mixture of two contradicting qualifiers leads to "const" being diminished from "constant" to "read only by software". So yes, IMHO this is an obscure case and I never saw anybody using it in a professional (safety relevant etc.) environment.

author: NorthGuy
author_rank: Super Contributor
timestamp: January 05, 2019, 03:02:45 pm
content: Quote from: 0xdeadbeef on January 05, 2019, 10:18:02 amYou assume the "other thread" is programmed in C, which is not necessarily the case. These keywords are merely hints to the C compiler. If you declare something "const" the compiler must generate an error when you write to it. If you don't declare something "volatile", the compiler is allowed fetch the variable once and hold it in the register. Otherwise, these keywords don't change anything. This is specific to C (not even C++). A language may not have a notion of "const" or "volatile" at all (such as assembler, for example).From the C viewpoint, if you cannot write something you declare it as "const", and if you think something may be changed by outside forces you declare it as "volatile". That is, if you are at the reading end of a mailslot, it looks like "const volatile" to you.But, if you're on the other side of the mailslot, the situation is reverse - you can write, and the entity can never be changed by anything except your program. If you were writing a C program, you would not declare it neither "const" nor "volatile".

author: andersm
author_rank: Super Contributor
timestamp: January 05, 2019, 03:14:50 pm
content: Quote from: NorthGuy on January 05, 2019, 03:02:45 pmYou would declare it volatile, to prevent the compiler from optimizing away repeated writes.

author: janoc
author_rank: Super Contributor
timestamp: January 05, 2019, 03:46:15 pm
content: Quote from: 0xdeadbeef on January 05, 2019, 10:18:02 amYou don't even need threads to have a valid use case for const volatile type.I guess you have never seen a microcontroller register that is read-only for the user code but its value can change - typically registers for incoming UART/I2C/SPI/... data. Those are often memory mapped, so you would declare it as a pointer. Declaring that as const volatile is actually necessary because without the volatile qualifier the compiler could optimize the access out.Quote from: 0xdeadbeef on January 05, 2019, 10:18:02 amThat is actually incorrect and a ton of people fall into this trap, confusing const with something immutable.Const only says that the lvalue (= memory address, even if it is a simple variable and not explicitly a pointer, variable is only a name for a memory address somewhere that you can retrieve using the & operator) you are using to access the data is read-only. It saysnothing whatsoeverabout the value that the lvalue describes. Once you understand this, you will understand also why const volatile is perfectly fine and that a "const variable" can actually change after initialization.Const is atype qualifier, it deals only with the type of the variable. What happens with thevaluedescribed by that variable is outside of the scope of the standard. Look up pointer aliasing in C if you want to see real world examples.That you have never seen anybody using this is not really an argument. There is plenty of all kinds of code out there in the wild, not all code is up to the NASA standards and if you live with such assumptions as the one above, you are pretty much setting yourself up for a nasty surprise at some point.For example, look in these standard Cortex M3 headers (all ARM Cortex M3 MCUs use this), line 204 onwards:https://github.com/ARM-software/CMSIS/blob/master/CMSIS/Include/core_cm3.hCode:/* IO definitions (access restrictions to peripheral registers) *//**\defgroup CMSIS_glob_defs CMSIS Global Defines<strong>IO Type Qualifiers</strong> are used\li to specify the access to peripheral variables.\li for automatic generation of peripheral register debug information.*/#ifdef __cplusplus#define __I volatile /*!< Defines 'read only' permissions */#else#define __I volatile const /*!< Defines 'read only' permissions */#endif#define __O volatile /*!< Defines 'write only' permissions */#define __IO volatile /*!< Defines 'read / write' permissions *//* following defines should be used for structure members */#define __IM volatile const /*! Defines 'read only' structure member permissions */#define __OM volatile /*! Defines 'write only' structure member permissions */#define __IOM volatile /*! Defines 'read / write' structure member permissions */Another example from a bit more recent CMSIS, showing use of this for I2C registers on LPC18xx series MCUshttps://github.com/ARM-software/CMSIS_5/blob/develop/CMSIS/Pack/Example/CMSIS_Driver/I2C_LPC18xx.h(scroll to the very bottom):Code:/* I2C Resource Configuration */typedef struct {LPC_I2Cn_Type *reg; // I2C register interfaceIRQn_Type i2c_ev_irq; // I2C Event IRQ Numbervolatile uint32_t *base_clk_reg; // Base clock registervolatile uint32_t *pclk_cfg_reg; // Peripheral clock config registerconst volatile uint32_t *pclk_stat_reg; // Peripheral clock status registeruint32_t rgu_val; // Peripheral reset valueI2C_CTRL *ctrl; // Run-Time control information} const I2C_RESOURCES;So much about its use in "professional (safety relevant) environment".

author: janoc
author_rank: Super Contributor
timestamp: January 05, 2019, 03:59:42 pm
content: Quote from: NorthGuy on January 05, 2019, 01:25:58 amAnyone can have opinion about whatever they want but that doesn't make them correct.

author: Jeroen3
author_rank: Super Contributor
timestamp: January 05, 2019, 04:44:38 pm
content: static, const and volatile are the most complicated keywords in C.Remember that C is a tool to write machine code. C doesn't know about what it runs on. You do.Keywords only limit whatyoumay do.But it still is C, if you must you still may do so. You can work completely type-oblivious in C using void.Types are actually a common source of bugs. And also a reason for debate. Hence why C++ is equipped withauto. Or some languages not even having types at all. (javascript)But not all languages are easily compatible with every platform or intended function. You can't really use javascript for embedded or kernel drivers for example.

author: janoc
author_rank: Super Contributor
timestamp: January 05, 2019, 06:59:00 pm
content: Quote from: Jeroen3 on January 05, 2019, 04:44:38 pmYou have obviously not seen the definition forrestrict(a slightly more understandable explanation:https://en.wikipedia.org/wiki/Restrict)Quote from: Jeroen3 on January 05, 2019, 04:44:38 pmThat's actually completely wrong, on several fronts (I will get to theautokeyword below).Languages like Javascript (or Python, for ex.) of course do have types. They are justdynamically typed- i.e. the type is associated with the value (string, int, float, etc.), often using some sort of atagstored with the data, not the variable that is used to refer to it. The "type" of a variable depends on what value has been assigned to it, so it could hold a string at one moment and an int two seconds later.In contrast, languages such as C, C++, Java, Haskell and many others arestatically typed- the type is known at compile time and does not normally change at runtime (ignoring type casting, type punning and similar).Dynamic typing is of course convenient - no type declarations, you can store everything anywhere you want, etc. The downside is pretty much unmaintainable code unless extreme care is taken, the compiler will not warn you that you are passing a string to a function that expects numbers as arguments and similar -> lot of runtime bugs and problems. There are ways out of this, e.g. obsessive use of automated tests, using type annotations where you actually declare what argument types is your function expecting (Python, Lisp have these, Javascript doesn't) but all that requires programmer's discipline.Static typing avoids these issues. For example Haskell is a strongly statically typed language where if you get the code to compile correctly, it is almost assured the code is also correct. That's because the strong typing and the very powerful type system that Haskell has allow the compiler to reason about the behaviour of your code in detail - much more than e.g. C/C++ compiler can. Static typing also allows for much more powerful optimization techniques than dynamically typed languages can perform.Dynamicaly typed languages have to typically resort to things like JIT which actually "learn" what the types of the data are at runtime before being able to optimize the code. Whereas statically typed language can be optimized at compile time and often to much higher degree because the compiler is able to reason about the data - e.g. replace constants with values, eliminate constant expressions (think constexpr in C++) with precompiled values at compile time, eliminating entire files of code in the process.Good example of this is the Kvasir library (https://github.com/kvasir-io/Kvasir) - it allows to write quite a bit of complex code e.g. initializing MCU registers, while checking that you don't write into bits that are not writeable or try to write an invalid value (e.g. 6bit value into 4bit register part - if you are doing it using bit manipulations you get no warning).And all this (even multiple bit manipulations/assignments in a single register) typically compiles into a simple assignment because all this stuff is done as constant expressions and type manipulations (via C++ templates) so the compiler can optimize it. So you gain correctness, code readability and safety all the while not paying for it with runtime performance or code size. It costs only extra compilation time and possibly some horrific C++ error messages from the template instantiations if you screw up.And reauto- C++autodoes notremove any types from the language. It is just a syntactic sugar so that one doesn't need to write the type when the compiler is able to deduce it automatically - which is only possible because the language is statically typed, so the compiler can compute what the resulting type of the expression will be. The variable is still typed the same as if you wrote the type there by hand.Types actually help prevent the bugs, lack of the type information at compile time is the source of problems.(And the fact that Javascript or Python aren't used for writing kernel drivers has nothing to do with types but a different language focus, even though both can and do run on embedded hw too. You are also not writing website code in C++. But that's a different debate, let's not turn this into a pissing context about the merits of this vs that programming language)