Proposal: [299] 2C! and 2C@


This page is dedicated to discussing this specific proposal


sxjh9935avatar of sxjh9935 [299] 2C! and 2C@Proposal2023-06-07 01:09:02



Change Log:

2023-06-07 - First draft of proposal.


When using Forth for system programming, it is not usual for 16-bit values to be written or read. There are Forth words that handle 64-bit values, 32-bit values, 8-bit values but not 16-bit values.


Introduce two new words - 2C! and 2C@.

The signatures for the two words are as follows-

2C! ( x1 x2 c-addr -- )

2C@ ( c-addr -- x1 x2 )

In both instances, x1 is the value at the higher address (c-addr+1) and x2 is the value at the lower address (c-addr).


These words should form part of the CORE dictionary.

The words 2C! and 2C@ should be, respectively, inserted at 6.1.0360 and 6.0365.

The following word definitions should be inserted.

( x1 x2 c-addr -- )
Store char pair at c-addr with x2 at c-addr and x1 at the next c-addr.

( c-addr -- x1 x2 )
Fetch char pair at c-addr. x2 is stored at c-addr and x1 at the next c-addr.

Reference implementation:



These implementations were written without reference to other publicly available implementations.

After these implementations were written, the author checked whether such words are described in publicly available code. By sheer coincidence, the author found implementations nearly identical to 2C@. The difference being that 1+ was used rather than CHAR+. The author also found implementations of 2C! but such implementations made use of the return stack and such use of the return stack is unnecessary.

MitraArdronavatar of MitraArdron

You say There are Forth words that handle 64-bit values, 32-bit values, 8-bit values but not 16-bit values.. I'm curious - what words do you have in mind. 2! and 2@ work on cell pairs and the size of a cell is system dependent. In my [WebForth] for example in the ESP8266 you set #define CELLL 4 to work on 32 bit cells, in which case 2@ fetches 64 bits but in Arduino you set #define CELLL 2 to work on 16 bit cells in which case 2@ fetches 32 bits.

For system programing it would be dangerous to use @ ! 2@ and 2! unless you knew for sure how this mapped to the underlying system architecture.

AntonErtlavatar of AntonErtl

Common practice for reading and writing 16-bit values is w@ ( addr -- u ) and w! ( x addr -- ). We have been discussing standardizing these and related words for many years, maybe we will get around to it at some point.

rcfg7943avatar of rcfg7943

Proposal author here. Apologises for my slow reply. I've been trying to reset the password to my account but it appears there is no way to do so. I've even tried contacting the site administrator via various email addresses that appear to be associated to this website but I receive no reply. Hence, the new account. If anyone can delete my old user 'sxjh9935', please do.

rcfg7943avatar of rcfg7943

@MitraArdron and @AntonErtl

Since posting my proposal, I've notice two other more recent proposals(i.e. 301 and 302) and it appears they address my needs and may be more consistent with current practices.

Given such, I think it is appropriate if this proposal is withdrawn in lieu of those more recent proposals.

But for the sake of completeness, I will address your questions.

@MitraArdron I am assuming that the cell have a width of 32-bits.

This allows 2! and 2@ for on 64-bit values, ! and @ for 32-bit values and C! and C@ for 8 bit values.

However, I appreciate this may create problems if the cell width was anything other than 32-bits. For example, if the cell width was 64-bits. If the cell width was 64-bits, you could probably address the issue using the 2C@/2C! words as proposed or C@/C! but then why wouldn't I just use the C@/C! in lieu of these words. Perhaps having words independent of the cell width (as per the aforementioned more recent proposals) will avoid this problem.

Fortunately @ and !, 2@ and 2! aren't dangerous in my circumstances but thank you for the concern. The implementation and operating system I'm working with is written largely in Forth and I'm very familiar with the implementation of the aforementioned words. I had raised this proposal because 16-bit words were required for the network driver and network stack implemented and I was surprised that something did not already exist in the published standards.


Thank you for pointing out these words. I wasn't aware of them. I hope these words and other related words are standardised within the CORE dictionary/library in the near future. I also note that they are the subject of the more recent proposals mentioned herein.

LeonWagneravatar of LeonWagner

The original contributor states that 2C@ and 2C! are for 16-bit access and this is not quite correct. They are for pairs of bytes in memory (or registers on some embedded systems). FORTH, Inc. has supplied 2C@ and 2C! for at least the past 30 years with our cross compilers for embedded systems. I just did a quick search of about 20 embedded Forth applications I have here on my computer and I found 180 instances of 2C@ and 132 instances of 2C!. Here's a simple example:

2 BUFFER: LBAT   \ Current and previous battery status

\ Update battery status, keeping previous
: !LBAT ( x -- )   LBAT C@ SWAP LBAT 2C! ;   

\ Return true if battery status has changed
: ?LBAT ( -- flag )   LBAT 2C@ <> ;   

However, 2C@ and 2C! are easily built from Standard words, so we've never proposed they be standardized.

Reply New Version