Strings in C

Thread Starter

Ian0

Joined Aug 7, 2020
13,132
Where do you think strings you've created at compile time exist? In the symbol table. During execution (aka 'runtime') the must exist in RAM. Your display routine should accept a pointer to the string as an argument, not a string. Just FYI.
At a guess the compiler would put them in a literal pool in ROM, and access them with the LDR R0,[PC,offset] instruction (it's an ARM, I assume others do the same). The routine that displays them doesn't need to copy the string, it just needs to know the start address and either length or terminating character, then it sends one character at a time to the display.
If I declared them all as char* arrays, it would also put the in a different bit of the ROM and the effect would be the same.
 

Thread Starter

Ian0

Joined Aug 7, 2020
13,132
As for worrying about efficiency, in general that's the mindset that needs to be used -- if the code is efficient enough, then it's efficient enough and readability/maintainability trump performance. But since the TS is talking about LCD displays, this is almost certainly some kind of embedded application and efficiency considerations can seldom be cavalierly dismissed when working with resource-starved processors. Most of my embedded programming back in the day was done on PICs using a 32 kHz watch crystal as the oscillator, so I could execute 8192 instructions/second, plus I also was limited to 2K instructions and had all of 128 bytes of RAM to work with -- you can bet I had efficiency very high on my list of priorities.
I started on 512byte PICs, and the mindset hasn't gone away, even now I've got 256k of Flash. I'd much prefer the processor to return to its WFI loop sooner rather than later. If the probability of having an error in code is a reasonably fixed percentage, the more code, the more errors.
Well written code tends to be efficient code. The really bloaty code is the stuff that the processor manufacturer gives you called "drivers".
Recently, I gave up on trying to understand how the Renesas IIC peripheral works, and wrote a bit-banging routine to do it. My routine was shorter than the code needed to run the peripheral.
 

MrAl

Joined Jun 17, 2014
13,704
Hello again,

What I had started to do is somethink like a Microsoft Foundation Class library, where you just wrap up everything you want to do.
For example, for a string array instead of loading every byte or whatever, create a wrapper that does it:
ArrayX(5,"MyString");

which loads "MyString" into ArrayX in location 5 so you can access it later, or change it again when needed.
That '5' could point to a pointer table instead though, so that you can use it easier, and the program reads as if it is just part of the language now.
For example:
GetArrayX(5,6);
could get the string at location 5 and load it into location 6.

What all this does is it makes working with strings a lot more routine and after these wrappers are found to be error free, then can be used in more projects with less worry about errors.
The other nice thing is you can create functions that do all kinds of things with strings this way.

I have not actually done this in the C language for a while now so the examples above may be too simplistic, but that's the main idea, and once you create a library like this you can use it over and over again for other projects.

I also took that to the next level by starting to use C++ Classes to do the wrappers. That expanded the functionality too and the readability of the program code improves also.

One thing I can not stress enough though is the use of remarks to annotate the code. After a lot of time has passed we can forget why we did something the way we did it, or how it basically works. Having enough notes within the program code files does wonders for remembering exactly what was what and why it was that way.
It's tempting to get lazy here, where we want to get the code working more than anything else. But I think the focus should be on annotating the code so we can understand it more clearly later in the coming years. It's not easy to get this disciplined with this, but I've learned over the years that it's a necessary evil.
 

Ya’akov

Joined Jan 27, 2019
10,235
Aside from efficiency, or anything else, there is a very good reason to put UI messages in a single, runtime mutable location—localization.
 

joeyd999

Joined Jun 6, 2011
6,281
Aside from efficiency, or anything else, there is a very good reason to put UI messages in a single, runtime mutable location—localization.
I've mentioned this previously in other threads:

I wish standard C supported the inclusion of resource files in a project. I'd much rather keep all my UI literals separate from the code. L10n, i18n, and maintenance would be much easier.
 

nsaspook

Joined Aug 27, 2009
16,323
I've mentioned this previously in other threads:

I wish standard C supported the inclusion of resource files in a project. I'd much rather keep all my UI literals separate from the code. L10n, i18n, and maintenance would be much easier.
Standard C doesn't but C is a very small standard. There are system and user libs for just about anything and you can always write a bespoke version perfectly suited for the application. You can embed binary files in executable using ld linker as that's really were the functionality should be, not in the C language standard.
 

MrAl

Joined Jun 17, 2014
13,704
Ha! This is how we got speed in the old Z80 days.
So true! Back then we had to have our bag of tricks and techniques both to achieve speed and restrict code size to fit into very limited memory and disk space.
If only more programmers of today had that experience we would probably not have bloat ware.
 

nsaspook

Joined Aug 27, 2009
16,323
So true! Back then we had to have our bag of tricks and techniques both to achieve speed and restrict code size to fit into very limited memory and disk space.
If only more programmers of today had that experience we would probably not have bloat ware.
People have selective memory about those great days of Z80 magic tricks. Sorry but while it was valuable, it also was a horrible way to design and write good software.
 

BobaMosfet

Joined Jul 1, 2009
2,211
True but the programming priesthood forbids (for IMO obvious very good reasons) that today.
Yes, in systems wee there is a pre-fetch cache only. In embedded systems, where there is no such pre-fetch, and memory is at a premium- it can be very useful and powerful (and in some cases the only means of increasing the embedded's capability- like paged memory management for larger programs that can't fit in what's available for example).
 

nsaspook

Joined Aug 27, 2009
16,323
Yes, in systems wee there is a pre-fetch cache only. In embedded systems, where there is no such pre-fetch, and memory is at a premium- it can be very useful and powerful (and in some cases the only means of increasing the embedded's capability- like paged memory management for larger programs that can't fit in what's available for example).
It depends on which embedded your talking about. For 8-16-bit controllers today voodoo tricks are not needed unless you're trying to cram new functionality in a 20yo controller instead of using something modern with hardware modules designed to eliminate the need for voodoo tricks. You can do this in hardware with only a few lines of code on modern 8-bit hardware.
https://forum.allaboutcircuits.com/...s-with-controlling-an-led.199346/post-1893329

Most 32-bit controllers have I/D caches and some have branch prediction with a real MMU with VM for demand paging of memory.
I use the PIC32Mk series for lots of projects.
https://developerhelp.microchip.com...s/mcu-mpu/32bit-mcu/PIC32/mk-memory-segments/
The ESP32 series (sold and used everywhere) also have cache to match processor speed with flash access times.
 
Last edited:
Top