这是我们在C ++类简介中得到的另一个“重塑方向”问题:
编写一个函数,该函数返回第一次出现的位置 字符串中的字符序列,即
strstr
的变体 功能。
我开始编写如下函数:
int strstr2(const char *text, const char *pattern) {
int pos = 0;
char *temp;
temp = text;
}
我以为我会记住该函数的字符串的第一个字符的地址以供将来使用,但是编译器说:
不能将类型为“ const char *”的值分配给类型为“ char *”的实体。
我知道一旦初始化常量就无法更改常量,但是为什么我不能将指向常量char的指针分配给另一个非常量指针呢?
我阅读了一些有关指针和常量的问题,似乎在this帖子中被接受的答案的底部可能回答了我的问题,但我不确定百分百,因为讨论仍在进行中对我来说太高级了。
我的第二个问题是,解决方法是什么?如何定义一个指向字符串开头的指针?
谢谢。
答案 0 :(得分:8)
这与const-correctness有关。 const char *text
表示text
是指向常量char
的指针。这意味着如果您尝试做类似的事情
*text = 'a'
由于您尝试修改const
对象,因此编译器将发出错误。如果可以的话
char *temp;
temp = text;
那你就可以做
*temp = 'a'
,即使您刚刚修改了const对象,也不会出错。这就是为什么C ++要求您实际上想抛弃const
的情况下使用const_cast
的原因(有一些用例,但到目前为止并不是您通常想要做的)。
危险,下面有龙。如果决定使用const_cast
,请非常小心让我们说您必须处理一个仅需char*
的旧API调用,但它保证不会修改,那么您可以使用类似
int wrap_api(const char *text)
{
return api_call(const_cast<char*>(text));
}
,这将是“可以的”,因为api_call
保证不会修改字符串。另一方面,如果api_call
可以修改,那么只有在text
指向的对象实际上不是像const这样的情况下,这才是合法的
char foo[] = "test"
wrap_api(foo);
如果foo
被修改,但将是合法的,但
const char foo* = "test"
wrap_api(foo);
如果foo
被修改并且是未定义的行为,将是不合法的。
答案 1 :(得分:2)
如果允许分配,您将可以合法地写:
Option Explicit
Sub CopyMyStuff2()
Dim wsSrc As Worksheet 'define source
Set wsSrc = ThisWorkbook.Worksheets("SourceSheet")
Dim wsDest As Worksheet 'define destination
Set wsDest = ThisWorkbook.Worksheets("Sheet3")
Dim FindList As Variant 'defind search words
FindList = Array("Tank Engine", "Weatherman")
Dim i As Long
Dim FindItm As Variant
For Each FindItm In FindList
Dim CopyRange As Range
Set CopyRange = FindMyRange(wsSrc.Range("A:L"), FindItm, "INFORMATION: " & FindItm)
If Not CopyRange Is Nothing Then
CopyRange.Copy wsDest.Range("A1").Offset(ColumnOffset:=i) 'note that if the first column uses merged cells the ColumnOffset:=i otherwise it is ColumnOffset:=i*12
i = i + 1
End If
Next FindItm
End Sub
Function FindMyRange(SearchInRange As Range, ByVal StartString As String, ByVal EndString As String) As Range
'find start
Dim FoundStart As Range
Set FoundStart = SearchInRange.Find(What:=StartString, LookAt:=xlWhole)
If FoundStart Is Nothing Then GoTo ERR_NOTHING_FOUND
'find end
Dim FoundEnd As Range
Set FoundEnd = SearchInRange.Find(What:=EndString, LookAt:=xlWhole, After:=FoundStart)
If FoundEnd Is Nothing Then GoTo ERR_NOTHING_FOUND
Set FindMyRange = SearchInRange.Parent.Range(FoundStart, FoundEnd).Resize(ColumnSize:=12)
Exit Function
ERR_NOTHING_FOUND:
FindMyRange = Nothing
End Function
但是在这种情况下,这会很糟糕,因为您将要写入一个常量。
标准可以表示*temp = 'x'; // write to char* is legal in general
分配是合法的,而temp = text
是未定义的行为,但这没有任何意义,因为{{ 1}}和*text = 'x'
是是否可以写入它。
因此,C ++禁止为T*
类型分配const T*
类型的值是为了避免以后做不好的事情,而是强迫您在其中使用T*
,这是合乎逻辑的这种情况。
答案 2 :(得分:1)
这是const-correctness类型安全性的一部分。由于text
是指向const char
的指针,因此您无法修改它指向的字符。这是一件好事,也是一项安全措施。
但是,如果允许向非常量字符分配指针,则整个安全性将失效!因为比起您您可以通过上述指针修改字符并绕过安全性!
因此,不允许进行此分配。要修复它,请将您的temp
也标记为const char指针:const char* temp
。