Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

How do I specify a c-string

Simon_Geard
New Contributor I
1,675 Views

I'm trying some code Steve posted years ago:

[fortran]

                ! Code for message box
                ret = MessageBox (         &
                    GetForegroundWindow(), & ! Handle to window
                    "Hello World!"C,           & ! Text (don't forget C-string)
                    "Example of using MessageBox"C, & ! Caption for title bar
                    MB_ICONINFORMATION + MB_OK) ! Type flags


[/fortran]

which works. In reality I want to post some useful information that is contained in a character variable but I can't figure out the correct syntax. In fact the only thing I've tried is using LOC but that doesn't compile.

[fortran]

              character(len=:), allocatable :: myvar

              myvar = 'Hello World!'

                ! Code for message box
                ret = MessageBox (         &
                    GetForegroundWindow(), & ! Handle to window
                    LOC(myvar),           & ! Text (don't forget C-string)
                    "Example of using MessageBox"C, & ! Caption for title bar
                    MB_ICONINFORMATION + MB_OK) ! Type flags


[/fortran]

Compiling with Intel(R) Visual Fortran Compiler XE 14.0.1.139 [Intel(R) 64]...

error #6633: The type of the actual argument differs from the type of the dummy argument.   [LOC]

 

Thanks.

0 Kudos
17 Replies
Steven_L_Intel1
Employee
1,675 Views

You don't use LOC, you just pass myvar. But you need to set the value of myvar as "'Hello World!'C

Alternatively you could pass TRIM(myvar)//''C

0 Kudos
Jacob_Williams
New Contributor III
1,675 Views

The "C syntax is an Intel extension, right? It's probably better to use the c_null_char variable in iso_c_binding.  Example:

use iso_c_binding,  only: c_null_char
character(len=:), allocatable :: myvar
myvar = 'Hello World!'//c_null_char

 

 

0 Kudos
Steven_L_Intel1
Employee
1,675 Views

Yes, it's an extension,but so is the use of Windows API routines. I agree that use of C_NULL_CHAR is a fine approach.

0 Kudos
andrew_4619
Honored Contributor III
1,675 Views

Steve Lionel (Intel) wrote:

Yes, it's an extension,but so is the use of Windows API routines. I agree that use of C_NULL_CHAR is a fine approach.

 

If the C postfix on strings is a language extension why no warning when compiling using /stand:f08?

 

0 Kudos
Steven_L_Intel1
Employee
1,675 Views

Because we missed adding that check. Already filed as issue DPD200246505.

0 Kudos
Steven_L_Intel1
Employee
1,675 Views

Fixed for a release later this year.

0 Kudos
dboggs
New Contributor I
1,675 Views

I have also done

myvar = 'Hello world!' // CHAR(0)

or

WRITE (myvar, *) 'Hello world!', CHAR(0)

and I THINK that worked also. Would have to do some digging to know for sure. Perhaps Steve or other could comment on this approach?

0 Kudos
Steven_L_Intel1
Employee
1,675 Views

The first is fine. One could also use C_NULL_CHAR from ISO_C_BINDING instead of CHAR(0).

The second will insert a blank at the beginning of myvar - I don't think you want that. You should use an explicit format rather than list-directed. It does seem a rather high-overhead method of getting the NULL in there.

0 Kudos
dboggs
New Contributor I
1,675 Views

Thanks Steve.

You're right of course about the list-directed format in case 2. I know this well. Kind of a separate issue though so I didn't even think about it here.

A rather "high-overhead" method of getting the NULL? Maybe, but there are certainly times when one needs to WRITE something into a string--perhaps several different variable values--in which case merely adding an additional value of CHAR(0) is pretty straightforward.

I like these techniques because they're 100 percent Fortran. No USE statement required referencing something that many people would have to look up. In fact I never heard of ISO_C_BINDING, know nothing about it, and probably have no use for it.

0 Kudos
Steven_L_Intel1
Employee
1,675 Views

Sure, there are cases where the WRITE makes sense. Concatenating with CHAR(0) is fine. But as for ISO_C_BINDING, if you're doing anything with null-terminated strings you are probably interfacing with C code and you'll find that useful for doing so in a standard manner.

0 Kudos
Anthony_Richards
New Contributor I
1,675 Views

So what's non-standard about CHAR(0)?
Is it the CHAR or the '0' ?
I cannot believe that the string terminating character presently used (Hex 0) is likely to be changed in future?
Too many things would break, surely?

Are we not being somewhat paranoid that Microsoft might change the terminator in future?

0 Kudos
Steven_L_Intel1
Employee
1,675 Views

I did not see anyone suggest that CHAR(0) was nonstandard.

0 Kudos
FortranFan
Honored Contributor III
1,675 Views

dboggs wrote:

... In fact I never heard of ISO_C_BINDING, know nothing about it, and probably have no use for it.

ISO_C_BINDING is simply means to an end, that of a standard way of achieving interoperability with C.  This feature introduced in Fortran starting with Fortran 2003 standard is a very valuable addition in my opinion.

0 Kudos
Steven_L_Intel1
Employee
1,675 Views

I would say that ISO_C_BINDING is one part of the C interoperability features of F2003. It is not the whole of it. I know that a lot of people use ISO_C_BINDING to mean C interoperability, but that's imprecise. Note that Fortran 2015 significantly extends C interoperability - I am in the middle of writing a Doctor Fortran post on this topic.

I brought up ISO_C_BINDING because it contains standard-specified definitions of things useful in interoperating with C, including named constants for things such as NULL, LF and CR.

0 Kudos
IanH
Honored Contributor III
1,675 Views

Anthony Richards wrote:
So what's non-standard about CHAR(0)?
Is it the CHAR or the '0' ?

If it is a nice day outside, you might be better off going for a walk rather than reading this, but speaking of Fortran processors in general (rather than ifort specifically), CHAR(0) returns a character of default character kind.  There's no requirement that the default character kind be the interoperable C character kind, and there's no guarantee that the character number zero in the collating sequence for default character is the all-bits-zero null character used to terminate C strings.  CHAR(0) is standard conforming, but the behaviour of that standard conforming code fragment is processor dependent.

Finding a Fortran processor implementation where CHAR(0) doesn't do what you would expect might be a little difficult though.

0 Kudos
andrew_4619
Honored Contributor III
1,675 Views

I had a nice walk outside and decided that achar(0) is "righter" than char(0)..... :-)

 

0 Kudos
Steven_L_Intel1
Employee
1,675 Views

This is perhaps why C_NULL_CHAR is a better choice as you're guaranteed it is the right character kind. 

0 Kudos
Reply