拿这段代码:
int main(void)
{
int var$ = 3;
printf("%d\n",var$);
}
这正确编译(GCC,Clang,MSVC)并按预期执行时打印3
。
但是,这段代码:
int main(void)
{
int var@ = 8;
printf("%d\n",var@);
}
这不会编译(GCC,Clang,MSVC),错误为stray '@' in program
。
查看C/C++ Operator List( Ctrl + F '为@
和$
),它们都不是运营商。
为什么var$
有效但var@
不是<?p?
答案 0 :(得分:4)
查看C11 Specification,关于标识符的第6.4.2节:
语义
2 标识符是一系列非数字字符(包括下划线
_
, 指定的小写和大写拉丁字母,以及其他字符和数字 6.2.1中描述的一个或多个实体。小写和大写字母是不同的。 标识符的最大长度没有特定限制。3 标识符中的每个通用字符名称应指定其编码的字符 在ISO / IEC 10646中属于D.1中规定的范围之一。 71)初始字符 不应是指定编码所属字符的通用字符名称 D.2中规定的范围之一。 实现可能允许多字节字符 它不是标识符中出现的基本源字符集的一部分; 哪些字符 它们与通用字符名称的对应关系是实现定义的。
(强调我的)
根据实施定义的行为GCC Manual:
- 标识符字符。
C和C ++标准允许标识符由“
_
”和字母数字字符组成。 C ++还允许通用字符名称。 C99及更高版本的C标准允许通用字符名称和实现定义的字符。GCC允许标识符中的“
$
”字符作为大多数目标的扩展名。无论std=
切换如何,都是如此,因为此扩展不能与符合标准的程序冲突。但是,在预处理汇编程序时,默认情况下,美元不是标识符字符。
(强调我的)
再次在Tokenization中,并在Idav1s's answer中提及:
作为扩展,GCC将“
$
”视为一封信。这是为了与某些系统(如VMS)兼容,其中“$
”通常用于系统定义的函数和对象名称。 “$
”不是严格符合模式的字母,或者如果您指定-$
选项。
由于VMS使用了许多系统定义的函数和名为 $
的对象,因此GCC允许将$
作为特定于实现的字符包含在内系统。
C规范未明确允许$
和@
等特殊字符位于标识符中,但实现时可能允许某些字符(例如此处为$
) 。例如,GCC允许大多数目标的标识符为$
。 Clang也是如此(因为它的大多数实现定义的行为与GCC相同)和MSVC。
答案 1 :(得分:2)
作为延期,海湾合作委员会将'$'视为一封信。这是为了与某些系统(如VMS)兼容,其中“$”通常用于系统定义的函数和对象名称。 '$'不是严格符合模式的字母,或者如果指定 - $选项。请参阅调用。
我稍微修改了您的/// Retrieves the device's location.
public final class DeviceLocation: NSObject, CLLocationManagerDelegate {
// MARK: - Properties
/// Handles the delivery of the device's current location.
private let locationManager = CLLocationManager()
/// The object responsible for handling the device's location-based updates.
public weak var deviceLocationDelegate: DeviceLocationDelegate?
// MARK: - Initialization
/// Returns an initialized `DeviceLocation` object.
public override init() {
super.init()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
}
// MARK: - CLLocationManagerDelegate
public func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
switch status {
case .authorizedAlways,
.authorizedWhenInUse:
startMonitoringLocationChanges()
default:
return
}
}
public func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let location = locations.last else {
return
}
print(location)
reverseGeocode(location)
deviceLocationDelegate?.deviceLocation(self, didReceiveCoordinate: location.coordinate)
}
public func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print(error)
deviceLocationDelegate?.deviceLocation(self, didFailToReceiveCoordinate: error)
}
// MARK: - Helpers
/// Requests access to the user's location while in use.
public func requestLocationAccess() {
if CLLocationManager.locationServicesEnabled() {
locationManager.requestAlwaysAuthorization()
}
}
/// Starts tasks associated with monitoring the device's location.
public func startMonitoringLocationChanges() {
locationManager.startMonitoringSignificantLocationChanges()
}
/// Retrieves information for a location from a reverse-geocode query.
/// - parameter location: The `CLLocation` instance.
private func reverseGeocode(_ location: CLLocation) {
let geocoder = CLGeocoder()
geocoder.reverseGeocodeLocation(location) { (placemarks, error) in
if let geocodeError = error {
print(geocodeError)
self.deviceLocationDelegate?.deviceLocation(self, didFailToReverseGeocode: geocodeError)
return
}
guard let placemark = placemarks?.last else {
return
}
self.deviceLocationDelegate?.deviceLocation(self, didFinishReverseGeocodeWithLocation: (city: placemark.locality, state: placemark.administrativeArea))
}
}
}
代码段(以消除我们不关心的警告)并添加严格符合标志here:
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0-m01</version>
</dependency>
因此,如果var$
被赋予正确的标记,$ gcc -Wall -std=gnu99 -ansi -pedantic -Werror -O2 -o a.out source_file.c
Error(s):
source_file.c: In function ‘main’:
source_file.c:4:13: error: '$' in identifier or number [-Werror]
int var$ = 3;
^
cc1: all warnings being treated as errors
也不会编译。
答案 2 :(得分:1)
嗯,严格来说,var$
也无效。
有些编译器允许您使用$
作为标识符中的字符,以及a
- z
,A
- Z
,0
- 9
和_
。这是一个非标准的扩展。它很有用,因为其他语言的编译器(我认为包括FORTRAN)允许在标识符中使用$
,并且您可能正在尝试编写与其他语言互操作的C代码。显然gcc是允许这种扩展的编译器之一。
允许@
的扩展名会更加不寻常。我可能曾经看过一个奇怪的编译器让你使用它,但由于我知道没有用它,对它的需求较少,我想没人会提供它。